题意:给定一张图,按照输入的边逐个删除,求每次删除一条边之后图的联通块数量。
分析:反向并查集求联通分量,假设起始各个点都不连通,接着从最后一条边开始添加,如果新加入的边联通了两个联通块,则联通分量减1(保存在数组中),最后正序输出结果即可。
#include<iostream>
#include<algorithm>
using namespace std;
int p[10005];
struct EDGE
{
int x,y;
} edge[100005];
int ans[100005];
bool Init(int n)
{
for(int i=0;i<n;i++)
p[i]=i;
return true;
}
int Find(int x)
{
int r,i,j;
r=x;
while(r!=p[r]) r=p[r];
i=x;
while(i!=p[i]) //路径压缩
{
j=p[i];
p[i]=r;
i=j;
}
return i;
}
bool Merge(int x,int y)
{
int tx,ty;
tx=Find(x);
ty=Find(y);
if(tx==ty) return false;
p[tx]=ty;
return true;
}
int main()
{
int N,M,i,u,v,sum;
while(scanf("%d%d",&N,&M)==2)
{
Init(N);
for(i=0;i<M;i++)
scanf("%d%d",&edge[i].x,&edge[i].y);
sum=N;
for(i=M-1;i>=0;i--)
{
ans[i]=sum;
u=Find(edge[i].x);
v=Find(edge[i].y);
if(u!=v) //合并两个联通快,连通分量减1.
{
Merge(u,v);
sum--;
}
}
for(i=0;i<M;i++)
printf("%d\n",ans[i]);
}
return 0;
}原文地址:http://blog.csdn.net/a809146548/article/details/45876669