1. 程式人生 > >(圖論)51NOD 1212 無向圖最小生成樹

(圖論)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\n",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\n", 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\n", ans);
85     }
86 }