(图论)51NOD 1212 无向图最小生成树
Posted ekalos-blog
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了(图论)51NOD 1212 无向图最小生成树相关的知识,希望对你有一定的参考价值。
N个点M条边的无向连通图,每条边有一个权值,求该图的最小生成树。
输入
第1行:2个数N,M中间用空格分隔,N为点的数量,M为边的数量。(2 <= N <= 1000, 1 <= M <= 50000) 第2 - M + 1行:每行3个数S E W,分别表示M条边的2个顶点及权值。(1 <= S, E <= N,1 <= W <= 10000)
输出
输出最小生成树的所有边的权值之和。
输入样例
9 14 1 2 4 2 3 8 3 4 7 4 5 9 5 6 10 6 7 2 7 8 1 8 9 7 2 8 11 3 9 2 7 9 6 3 6 4 4 6 14 1 8 8
输出样例
37
解:Kruskal算法(排序后添加边)的两种实现(时间消耗差不多):
1 #include <stdio.h> 2 #include <stdlib.h> 3 #include <string.h> 4 5 typedef struct Graph 6 { 7 int s,e,w; 8 }graph; 9 10 int cmp(const void *a,const void *b) 11 { 12 return (*(graph *)a).w>(*(graph *)b).w?1:-1; 13 } 14 15 graph p[50005]; 16 int vis[1005]; 17 18 int main() 19 { 20 int n,m; 21 while(scanf_s("%d%d",&n,&m)!=EOF) 22 { 23 int i,j,ans=0; 24 memset(vis,0,n); 25 for(i=0;i<m;i++) scanf_s("%d%d%d",&p[i].s,&p[i].e,&p[i].w); 26 qsort(p,m,sizeof(graph),cmp); 27 vis[p[0].s]=1; 28 vis[p[0].e]=1; 29 ans+=p[0].w; 30 for(i=0;i<n-2;i++) 31 { 32 for(j=0;j<m;j++) 33 { 34 if((vis[p[j].s]==0&&vis[p[j].e]==0)||(vis[p[j].s]&&vis[p[j].e])) 35 continue; 36 else 37 { 38 vis[p[j].s]=1; 39 vis[p[j].e]=1; 40 ans+=p[j].w; 41 break; 42 } 43 } 44 } 45 printf("%d ",ans); 46 } 47 return 0; 48 }
1 #include<stdio.h> 2 #include<stdlib.h> 3 #include<malloc.h> 4 5 typedef struct GRAPH 6 { 7 int s, e, w; 8 }graph; 9 10 11 int cmp(const void *a, const void *b) 12 { 13 return ((graph *)a)->w > ((graph *)b)->w ? 1 : -1; 14 } 15 16 graph p[50005]; 17 int *vis[1005]; 18 19 int main() 20 { 21 int n, m; 22 while (scanf_s("%d%d", &n, &m) != EOF) 23 { 24 int ans = 0; 25 for (int i = 0; i < m; ++i) scanf_s("%d%d%d", &p[i].s, &p[i].e, &p[i].w); 26 qsort(p, m, sizeof(graph), cmp); 27 for (int i = 0, j = 0; i < m; ++i) 28 { 29 int *tmp = (int *)malloc(sizeof(int)); 30 if (vis[p[i].e] == NULL) 31 { 32 if (vis[p[i].s] == NULL) 33 { 34 *tmp = j++; 35 vis[p[i].e] = vis[p[i].s] = tmp; 36 } 37 else 38 { 39 vis[p[i].e] = vis[p[i].s]; 40 free(tmp); 41 } 42 } 43 else if (vis[p[i].s] == NULL) 44 { 45 vis[p[i].s] = vis[p[i].e]; 46 free(tmp); 47 } 48 else 49 { 50 int *a, *b; 51 for (a = vis[p[i].s]; *a > 505; a = *a); 52 for (b = vis[p[i].e]; *b > 505; b = *b); 53 if (*a == *b) 54 { 55 free(tmp); 56 continue; 57 } 58 else 59 { 60 *tmp = *a; 61 *b = *a = tmp; 62 } 63 } 64 ans += p[i].w; 65 } 66 printf("%d ", ans); 67 } 68 }
Prim算法(排序后添加点)(写的不好,时间消耗比上面的长):
1 #include <stdio.h> 2 #include <malloc.h> 3 #include <string.h> 4 5 #define MIN(a,b) (pt[a]->pr<pt[b]->pr?a:b) 6 7 typedef struct POINT 8 { 9 struct POINT *p; 10 int ed,pr; 11 }point; 12 13 point *pt[1005]; 14 int vis[2][1005]; 15 int main() 16 { 17 int n, m; 18 while (scanf_s("%d%d", &n, &m) != EOF) 19 { 20 int ans = 0; 21 while (m--) 22 { 23 int a, b, c; 24 scanf_s("%d%d%d", &a, &b, &c); 25 point *tmp1 = (point *)malloc(sizeof(point)), *tmp2 = (point *)malloc(sizeof(point)); 26 tmp1->ed = b; 27 tmp2->ed = a; 28 tmp1->pr = tmp2->pr = c; 29 if (pt[a] == NULL|| tmp1->pr < pt[a]->pr) 30 { 31 tmp1->p = pt[a]; 32 pt[a] = tmp1; 33 } 34 else for (point *tmp0 = pt[a], *tmp = pt[a]; tmp0 != NULL; tmp = tmp->p) 35 { 36 if (tmp == NULL||tmp1->pr < tmp->pr) 37 { 38 tmp1->p = tmp0->p; 39 tmp0->p = tmp1; 40 break; 41 } 42 tmp0 = tmp; 43 } 44 if (pt[b] == NULL || tmp2->pr < pt[b]->pr) 45 { 46 tmp2->p = pt[b]; 47 pt[b] = tmp2; 48 } 49 else for (point *tmp0 = pt[a], *tmp = pt[b]; tmp0 != NULL; tmp = tmp->p) 50 { 51 if (tmp == NULL || tmp2->pr < tmp->pr) 52 { 53 tmp2->p = tmp0->p; 54 tmp0->p = tmp2; 55 break; 56 } 57 tmp0 = tmp; 58 } 59 } 60 vis[0][1] = 1; 61 vis[1][1] = 1; 62 for (int i = 1; i < n; i++) 63 { 64 int tmp = 0; 65 for (int j = 1; j <= i; j++) 66 { 67 if (pt[vis[0][j]] == NULL) continue; 68 else if(vis[1][pt[vis[0][j]]->ed]!=1) 69 { 70 if (0 == tmp) tmp = vis[0][j]; 71 else tmp = MIN(tmp, vis[0][j]); 72 } 73 else 74 { 75 pt[vis[0][j]] = pt[vis[0][j]]->p; 76 j--; 77 } 78 } 79 vis[0][i+1] = pt[tmp]->ed; 80 vis[1][pt[tmp]->ed] = 1; 81 ans += pt[tmp]->pr; 82 pt[tmp] = pt[tmp]->p; 83 } 84 printf("%d ", ans); 85 } 86 }
以上是关于(图论)51NOD 1212 无向图最小生成树的主要内容,如果未能解决你的问题,请参考以下文章