题意:给定一张图,按照输入的边逐个删除,求每次删除一条边之后图的联通块数量。
分析:反向并查集求联通分量,假设起始各个点都不连通,接着从最后一条边开始添加,如果新加入的边联通了两个联通块,则联通分量减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