众所周知求最小生成树的两种方法:
1、Kruskal
2、Prim
这里只挂第一种,因为noip掌握第一种就够了。
两种做法的区别可以参考这个博客:http://blog.csdn.net/mollnn/article/details/52589741
人人都说prim简单kruskal难..但我怎么就只会kruskal呢..
下面搬个题吧:
Bessie 计划调查N (2 <= N <= 2,000)个农场的干草情况,它从1号农场出发。
农场之间总共有M (1 <= M <= 10,000)条双向道路,所有道路的总长度不超过1,000,000,000。有些农场之间存在着多条道路,所有的农场之间都是连通的。 Bessie希望计算出该图中最小生成树中的最长边的长度。
输入格式:两个整数N和M。
接下来M行,每行三个用空格隔开的整数A_i, B_i和L_i,表示A_i和 B_i之间有一条道路长度为L_i。
输出格式:一个整数,表示最小生成树中的最长边的长度。
输入样例:
3 3
1 2 23
2 3 1000
1 3 43
输出样例:
43
很容易就能看出来是最小生成树的问题。
Kruskal
维护一个并查集,并按照最短路进行加入数集。
1 #include<cstdio> 2 #include<cmath> 3 #include<algorithm> 4 using namespace std; 5 struct node{ 6 int start,end,value; 7 }a[10005]; 8 int cmp(node x,node y){ 9 return x.value<y.value; 10 } 11 int n,m,f[2005],ans; 12 int cha(int x){ 13 if(f[x]!=x){ 14 return cha(f[x]); 15 }return f[x]; 16 } 17 int bing(int x,int y){ 18 x=cha(x); 19 y=cha(y); 20 if(x!=y){ 21 f[x]=y; 22 } 23 } 24 int main(){ 25 scanf("%d%d",&n,&m); 26 for(int i=1;i<=n;i++){ 27 f[i]=i; 28 } 29 int r,b,q; 30 for(int i=1;i<=m;i++){ 31 scanf("%d%d%d",&r,&b,&q); 32 a[i].start=r; 33 a[i].end=b; 34 a[i].value=q; 35 } 36 sort(a+1,a+1+m,cmp); 37 for(int i=1;i<=m;i++){ 38 int xxx=cha(a[i].start); 39 int yyy=cha(a[i].end); 40 if(xxx!=yyy){ 41 ans=fmax(ans,a[i].value); 42 bing(a[i].start,a[i].end); 43 } 44 } 45 printf("%d",ans); 46 return 0; 47 }