标签:
#include<iostream> using namespace std; int f[1000]={0},n,m,k,sum=0; //这里是初始化,数组里面存的是自己数组下表的编号 void init() { int i; for(i=1;i<=n;i++) { f[i]=i; } } //这是找爹的递归函数,不停地找爹,直到找到祖宗为止,其实就是找犯罪团伙的最高领导人,“擒贼先擒王”原则 int getf(int v) { if(f[v]==v) { return v; } else { //这里是路径压缩,每次在函数返回的时候,顺带把路上遇到的人的"BOSS"改为最后找到的祖宗的编号, //也就是犯罪团伙的最高领导人编号。这样可以提高找到犯罪团伙的最高领导人(其实就是树的祖先)的速度。 f[v]=getf(f[v]); return f[v]; } } //这里是合并两子集合的函数 void merge(int v,int u) { int t1,t2; t1=getf(v); t2=getf(u); if(t1!=t2)//判断两个节点是否在同一个集合中,即是否为同一个祖先 { f[t2]=t1; //“靠左原则”,左边变为右边的BOSS。几把右边的集合,作为左边集合的子集合 //经过路径压缩以后,将分f[u]的根的值也赋值为v的祖先f[t1]。 } } int main() { int i,x,y; cin>>n>>m; init(); for(i=1;i<=m;i++) { cin>>x>>y; merge(x,y); } for(i=1;i<=n;i++) { if(f[i]==i) sum++; } for(i=1;i<=n;i++) { cout<<f[i]<<" "; } cout<<endl; cout<<sum<<endl; return 0; } /* 10 9 1 2 3 4 5 2 4 6 2 6 8 7 9 7 1 6 2 4 */
版权声明:本文为博主原创文章,未经博主允许不得转载。
标签:
原文地址:http://blog.csdn.net/ingnight/article/details/47728789