并查集讲解: http://blog.csdn.net/zark721/article/details/77816406
原题:http://acm.hdu.edu.cn/showproblem.php?pid=1232
#include<cstdio> int pre[1010];//记录每一个节点的跟节点 int find(int x)//寻找x的根节点 { int r=x; while(pre[r]!=r)//找父亲 { r=pre[r]; } //压缩,修改自己和上级的pre,全部直接变成老大 int j=x,k; while(j!=r) { k=pre[j];//保存上级 pre[j]=r;//自己的上级变成老大 j=k; } return r; } void join(int x,int y)//合并函数 { int fx=find(x); int fy=find(y); if(fx!=fy)//如果我们两个的老大不一样 { pre[fx]=fy;//结盟 } } int n,m; void init()//初始化 { for(int i=1;i<=n;i++) { pre[i]=i; } } int main() { scanf("%d",&n); while(n!=0) { scanf("%d",&m); init();//初始化 for(int i=0;i<m;i++) { int p1,p2; scanf("%d %d",&p1,&p2); join(p1,p2); } int ans=0; for(int i=1;i<=n;i++) { if(pre[i]==i) { ans++; } } printf("%d\n",ans-1); scanf("%d",&n); } return 0; }