标签:
这道题 就是简单的最小生成树算法的应用啦,很明显的..而且把所有边都给出来了,所以就试着自己把prim和kruscal一起实现了.
1.prim算法实现
1 #include<iostream> 2 #include<stdio.h> 3 #include<string.h> 4 #include<algorithm> 5 using namespace std; 6 #define maxn 105 7 #define INF 0x3f3f3f3f 8 bool visit[maxn]; 9 int cost[maxn][maxn]; 10 int mincost[maxn]; 11 int n,min_cost,index; 12 int prim() 13 { 14 int res = 0, index = 1; 15 for(int i = 1;i <= n;i++) 16 mincost[i] = cost[i][1]; 17 mincost[1] = 0; 18 memset(visit,false,sizeof(visit)); 19 visit[1] = true; 20 for(int i = 1 ; i <= n; i++) 21 { 22 min_cost = INF; 23 for(int j = 1; j <= n; j++) 24 { 25 if(mincost[j]<min_cost && !visit[j]) 26 { 27 min_cost = mincost[j]; 28 index = j; 29 } 30 } 31 visit[index] = true; 32 for(int k = 1; k <= n; k++) 33 { 34 if(!visit[k] && cost[k][index] < mincost[k]) 35 mincost[k] = cost[k][index] ; 36 37 } 38 39 } 40 for(int i = 1 ;i <=n;i++) 41 res += mincost[i]; 42 return res; 43 } 44 int main() 45 { 46 //freopen("hdu 1233.txt","r",stdin); 47 int a,b,d; 48 while(scanf("%d",&n),n) 49 { 50 memset(cost,INF,sizeof(cost)); 51 for(int i = 0 ;i < n * (n-1) / 2 ; i ++ ) 52 { 53 scanf("%d %d %d",&a,&b,&d); 54 cost[a][b] = cost[b][a] = d; 55 } 56 printf("%d\n",prim()); 57 } 58 59 return 0; 60 61 }
2.通过stl库的优先队列实现的kruscal算法
因为只用到了并查集的简单合并,所以并没有通过秩来进行合并,没有必要做冗余的步骤.这题可能数据量比较小,用优先队列并没有起到运行速度优化的作用.
1 #include <iostream> 2 #include <stdio.h> 3 #include <string.h> 4 #include <queue> 5 using namespace std; 6 #define maxn 105 7 int father[maxn]; 8 int n; 9 struct node{ 10 int u , v; 11 int cost ; 12 friend bool operator < ( node a, node b){ 13 return a.cost > b.cost; 14 }; 15 }; 16 priority_queue<node> game; 17 void init() 18 { 19 for(int i = 1 ;i <= n; i++) 20 { 21 father[i] = i; 22 } 23 } 24 int find(int x) 25 { 26 if(father[x] == x) 27 return x; 28 return father[x] = find(father[x]); 29 } 30 void unite(int x,int y) 31 { 32 int fx = find(x),fy = find(y); 33 if(fx == fy) 34 return ; 35 father[fy] = fx; 36 } 37 int kruscal() 38 { 39 int count = 0 ,res = 0; 40 node q; 41 while(!game.empty()) 42 { 43 q = game.top(); 44 game.pop(); 45 if(count == n ) 46 return res; 47 if( find(q.u)!=find(q.v)) 48 { 49 unite(q.u,q.v); 50 count++; 51 res += q.cost; 52 } 53 } 54 return res; 55 } 56 int main() 57 { 58 //freopen("hdu 1233.txt","r",stdin); 59 int a,b,d,t; 60 while(scanf("%d",&n),n) 61 { 62 init(); 63 t = 0; node s; 64 for(int i = 0 ;i < n * (n-1) / 2 ; i ++ ) 65 { 66 scanf("%d %d %d",&a,&b,&d); 67 //cost[a][b] = cost[b][a] = d; 68 s.u = a ; 69 s.v = b; 70 s.cost = d; 71 game.push(s); 72 } 73 printf("%d\n",kruscal()); 74 } 75 return 0; 76 }
3.通过结构体数组记录边与定点信息实现的kruscal算法
1 #include <iostream> 2 #include <stdio.h> 3 #include <string.h> 4 #include <algorithm> 5 using namespace std; 6 #define maxn 105 * 60 7 #define INF 0x3f3f3f3f 8 int father[maxn]; 9 int n; 10 struct node{ 11 int u , v; 12 int w; 13 }edge[maxn]; 14 void init() 15 { 16 for(int i = 0 ;i <= n ;i++) 17 father[i] = i; 18 } 19 int find(int x) 20 { 21 if(father[x]==x) 22 return x; 23 return father[x]=find(father[x]); 24 } 25 void unite(int x,int y) 26 { 27 int fx = find(x) , fy = find(y); 28 if(fx == fy) 29 return ; 30 father[fy] = fx; 31 } 32 bool cmp(node a , node b) 33 { 34 return a.w < b.w; 35 } 36 int kruscal(int t) 37 { 38 int res = 0,count = 0; 39 int u,v; 40 for(int i = 0 ;i < t; i++) 41 { 42 u = edge[i].u; 43 v = edge[i].v; 44 if(count == n) 45 return res; 46 if(find(u)!=find(v)) 47 { 48 unite(u,v); 49 count++; 50 res += edge[i].w; 51 52 } 53 54 } 55 return res; 56 } 57 int main() 58 { 59 //freopen("hdu 1233.txt","r",stdin); 60 int a,b,d; 61 int t ; 62 while(scanf("%d",&n),n) 63 { 64 init(); 65 t= 0; 66 for(int i = 0 ;i < n*(n-1)/2 ; i++) 67 { 68 scanf("%d %d %d",&a,&b,&d); 69 edge[t].u = a; 70 edge[t].v = b; 71 edge[t++].w = d; 72 } 73 sort(edge,edge+t,cmp); 74 printf("%d\n",kruscal(t)); 75 } 76 return 0; 77 }
值得注意的是,排序是对所有读入的数据排序,不是对前n个数据排序,因为给出的数据量很小,所以一些细节错误是不容易看出来的..所以因为这个折腾了一会才发现,写的时候没发现,
对比了自己的代码半天,最后会宿舍重新检查一下就发现了.总之,就是做事情要细心,不能想当然.
标签:
原文地址:http://www.cnblogs.com/xiaoniuniu/p/4391284.html