连通分支数减一就是还要修的路
1 #include<stdio.h> 2 int f[10005],n,m; 3 4 //初始化 5 void init() 6 { 7 for(int i=1;i<=n;i++) 8 f[i]=i; 9 } 10 //递归函数,不停的去找爹,直到找到祖宗为止 11 int getf(int v) 12 { 13 if(v == f[v]) 14 return v; 15 //路径压缩,函数返回时改变了爹的值,有利于后面找祖宗 16 else 17 { 18 f[v]=getf(f[v]); 19 return f[v]; 20 } 21 } 22 23 //合并两个子集的函数 24 void merge(int u,int v) 25 { 26 int t1=getf(u); 27 int t2=getf(v); 28 //判断两个结点是不是在同一个集合中 即是不是共祖宗 29 if(t1 != t2) 30 { 31 f[t2]=t1; 32 //靠左原则,将右边集合变成左边的子集合 33 //经过路径压缩后将f[u]的根的值也赋值为v的祖先f[t1] 34 } 35 } 36 37 int main() 38 { 39 int x,y,sum; 40 while(scanf("%d",&n),n) 41 { 42 scanf("%d",&m); 43 sum=0; 44 //初始化 45 init(); 46 47 for(int i=1;i<=m;i++) 48 { 49 //开始合并 50 scanf("%d %d",&x,&y); 51 merge(x,y); 52 } 53 54 //扫描连通分支数 55 for(int i=1;i<=n;i++) 56 { 57 if(f[i] == i) 58 sum++; 59 } 60 61 printf("%d\n",sum-1); 62 } 63 return 0; 64 }
原文:http://www.cnblogs.com/lmqpt/p/4729324.html