传送门:hdu4496
题意:一个无向图图中共有n个点,一次给出m条边,要求输出一次删除前k(0<=k<m)条边后,该图中连通分量的个数。
思路:逆向思维,当没有边即k=m-1是共有n个连通分量,从后往前插入每条边,并查集判断是否有合并。
代码:
#include<bits/stdc++.h>
using namespace std;
#define FFF freopen("in.txt","r",stdin);freopen("out.txt","w",stdout);
#define lson l,m,r<<1
#define rson m+1,r,r<<1|1
#define CLR(arr,val) memset(arr,val,sizeof(arr))
#define rep(i,l,r) for(int i=l;i<r;i++)
typedef long long ll;
typedef pair<int,int>pii;
typedef pair<ll,ll>pll;
typedef pair<double,double>pdd;
typedef pair<double,int>pdi;
const int INF=0x3f3f3f3f;
const int MOD=1000000007;
#define maxn 100010
struct edge{
int from;
int to;
}data[maxn];
int fa[maxn];
int n,m;
int ans[maxn];
void init()
{
rep(i,0,n)fa[i]=i;
}
int Find(int r)
{
return r==fa[r]?r:(fa[r]=Find(fa[r]));
}
bool Merge(int a,int b)
{
int aa=Find(a);
int bb=Find(b);
if(aa!=bb)
{
fa[aa]=bb;
return true;
}
return false;
}
int main()
{
// ios::sync_with_stdio(false);
// cin.tie(0);
// #ifndef ONLINE_JUDGE
// FFF
// #endif // ONLINE_JUDGE
while(~scanf("%d%d",&n,&m))
{
init();
rep(i,0,m)
scanf("%d%d",&data[i].from,&data[i].to);
ans[m-1]=n;
for(int i=m-1;i>0;i--)
{
if(Merge(data[i].from,data[i].to))
ans[i-1]=ans[i]-1;
else ans[i-1]=ans[i];
}
rep(i,0,m)printf("%d\n",ans[i]);
}
return 0;
}