1 4 6 1 2 10 2 3 10 3 1 10 1 4 1 2 4 1 3 4 1 1 3 5 6
4
讲解:两种算法对于解决这列题目,都非常的方便的,克鲁斯卡尔,有一种贪心的感觉,线按照权值进行排序,然后选择边,而 prim 算法也是寻找最小的边,但是看起来比较麻烦,比较省时间:
AC代码一:克鲁斯卡尔算法
1 2 #include<iostream> 3 #include<cstdio> 4 #include<algorithm> 5 #include<cstring> 6 #include<string> 7 #include<cmath> 8 #include<map> 9 #include<queue> 10 using namespace std; 11 struct T 12 { 13 int x,y,z; 14 }num[125010]; 15 int cmp(T a, T b) 16 { 17 if(a.z < b.z) 18 return 1; 19 return 0; 20 } 21 int main() 22 { 23 int i,j,k,t,m,n,g,a[505],aa; 24 cin>>t; 25 while(t--) 26 { 27 cin>>m>>n; 28 int ans=0,sum=0,maxx=10000000; 29 for(i=1; i<=m; i++)//初始化的时间要注意 30 a[i]=i; 31 for( i=0; i< n; i++) 32 cin>>num[i].x>>num[i].y>>num[i].z; 33 for(i=1;i<=m;i++) 34 { 35 cin>>aa; if(aa<maxx) maxx=aa; 36 } 37 sort(num,num+n,cmp);//按照权值进行排序 38 for(i=0;i< n && sum<m-1 ; i++) 39 { 40 for(k=num[i].x ; a[k]!=k ;k=a[k]) 41 a[k]=a[a[k]]; 42 for(g=num[i].y ; a[g]!=g ;g=a[g]) 43 a[g]=a[a[g]]; 44 if(k!=g) 45 { 46 a[g]=k; 47 ans=ans+num[i].z; 48 sum++; 49 } 50 } 51 cout<<ans+maxx<<endl; 52 } 53 return 0; 54 } 55
AC代码二:普利姆算法
1 #include<stdio.h> 2 #include<string.h> 3 #define MAX 1<<28 4 int map[505][505]; 5 int e,v; 6 int prime() 7 { 8 bool flag[505];//标记数组; 9 int path[505],i,j,sum=0;//path 路径 10 for(i=1; i<=v; i++) 11 { 12 flag[i]=0;// 全部标记为0; 13 path[i]=map[1][i];//把上面的一组数 14 } 15 flag[1]=1; 16 for(i=1; i<v; i++)// v 表示的是村庄数,寻找n-1条边 17 { 18 int k , min=MAX; 19 for(j=1; j<=v; j++) 20 { 21 if( !flag[j] && path[j]<min ) //如果这个节点没有标记,并且路径小于以前的 22 { 23 min=path[j];k=j; 24 //printf("%d ",path[j]); printf("%d \n",k); 25 } 26 } 27 sum+=path[k]; 28 //printf("***\n"); 29 flag[k]=1; 30 for(j=1; j<=v; j++) 31 { 32 if( !flag[j] && path[j] > map[k][j] )//如果大于已经存在的边了,就不要它了 33 path[j]=map[k][j]; //否则继续寻找下一个节点 34 } 35 } 36 return sum; 37 } 38 int main() 39 { 40 int n; 41 scanf("%d",&n); 42 while(n--) 43 { 44 int a,b,c,i; 45 scanf("%d%d",&v,&e); 46 memset(map,9999,sizeof(map)); 47 while(e--) 48 { 49 scanf("%d%d%d",&a,&b,&c); 50 if(map[a][b]) 51 map[a][b]=map[b][a]=c<map[a][b]?c:map[a][b];//如果后来再一次出现相同的路径,则保存最小的权值 52 } 53 int min=9999999,k; 54 for(i=0;i<v;i++) 55 { 56 scanf("%d",&k); 57 if(min>k) 58 min=k; 59 } 60 printf("%d\n",prime()+min); 61 } 62 return 0; 63 }
nyoj 38 布线问题 Kruskal and Prim,布布扣,bubuko.com
原文:http://www.cnblogs.com/lovychen/p/3664213.html