生成最小树-prim,Kruskal算法
prim算法:一个辅助数组,用来记录当前到达其他点的最短路程,它是更新点,从第一个点出发,把数组w[]初始化,即第一个点到达其他点的路程,每次选取一个最小的点,在把我
w[k]=0;然后再在改点选取比第一个到达其他点的最小值。即更新。
Kruskal算法:用一个结构体来记录边的性质,边的两端和长度,先把边的长度排序,然后依次选取,在选取时,把边的两端赋值为相等,即代表了同一个分量,所以每次选取都要判断
边的两端值是否相等。所以要用一个辅助数组来标记分量,根据MST性质,最短路程连接的点等于总共的点n-1个,如果用Kruskal算法,它的辅助数组的值将全部相等,这是Kruskal算法的技巧。而且更新恰好为n-1个。
下面以poj1287Networking为列。
用两种方法实现:
prim算法
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<stdio.h> 2 #include<string.h> 3 int min(int x, int y) 4 { 5 return x < y ? x : y; 6 } 7 const int INF = 0x3f3f3f3f; 8 int main() 9 { 10 int i,j,n,r,p,t,k,sum=0; 11 int a[51][51],w[3000]; 12 while(scanf("%d",&p),p) 13 { 14 scanf("%d",&n); 15 memset(a,0x3f,sizeof(a)); 16 memset(w,0x3f,sizeof(w)); 17 for(i=1;i<=n;i++) 18 { 19 scanf("%d%d",&r,&t); 20 scanf("%d",&a[r][t]); 21 a[t][r]=a[r][t]=min(a[t][r], a[r][t]); 22 } 23 for(i=1;i<=p;i++) 24 w[i]=a[1][i]; 25 w[1]=0; 26 for(i=1;i<p;i++) 27 { 28 int min=INF; 29 for(j=1;j<=p;j++) 30 if(w[j]<min && w[j]) 31 {k=j;min=w[j];} 32 w[k]=0,sum+=min; 33 for(j=1;j<=p;j++) 34 if(w[j]>a[k][j]) 35 w[j]=a[k][j]; 36 } 37 printf("%d\n",sum); 38 sum=0; 39 } 40 return 0; 41 }
Kruskal算法:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<cstdio> 2 #include<algorithm> 3 using namespace std; 4 struct node{ 5 int x,y,c; 6 }edge[3000]; 7 int f[55],n,p; 8 bool cmp(node a,node b) 9 { 10 if(a.c<b.c) return 1; 11 return 0; 12 } 13 int find(int x) 14 { 15 return x==f[x]?x:find(f[x]); 16 } 17 void krusal() 18 { 19 int i,sum=0; 20 for(i=1;i<=p;i++) 21 f[i]=i; 22 for(i=0;i<n;i++) 23 { 24 int x=find(edge[i].x); 25 int y=find(edge[i].y); 26 if(x!=y) 27 { 28 f[x]=y; 29 sum+=edge[i].c; 30 } 31 } 32 printf("%d\n",sum); 33 } 34 int main() 35 { 36 while(scanf("%d",&p),p) 37 { 38 scanf("%d",&n); 39 for(int i=0;i<n;i++) 40 scanf("%d%d%d",&edge[i].x,&edge[i].y,&edge[i].c); 41 sort(edge,edge+n,cmp); 42 krusal(); 43 } 44 return 0; 45 }