最小生成樹(Prim + Kruskal)

Prim算法 php

  構造過程:node

    1)任選一個點,以這個點開始,尋找該點能夠訪問的全部的邊;ios

    2)在能夠訪問的全部邊中找到最小邊,這個邊必須有一個點尚未訪問過(防止出現迴路),將尚未訪問的點加入集合,並記錄添加的邊;(加點法)算法

    3)尋找當前集合能夠訪問的全部邊,重複2過程,直到沒有新的點能夠加入,即成功構造出最小生成樹。spa

 

 

 

 

Kruskal算法code

  構造過程:blog

    1)初始狀態是全部點獨立的一個圖,並無邊相連;ci

    2)在邊集中選擇權值最小的最短邊,若是這條邊依附的頂點在圖中的不一樣連通份量上(不造成迴路),就將這條邊加進去,不然捨去這條邊繼續選擇下一條最短邊;get

    3)重複2過程,直到構造出最小生成樹。string

 

 


經過一道簡單例題來看看具體代碼如何實現:

題目連接:http://acm.hdu.edu.cn/showproblem.php?pid=1233

 Prime寫法:

 1 #include<iostream>
 2 #include<cstring>
 3 using namespace std;
 4 const int INF = 0x3f3f3f3f;
 5 int n, ans;
 6 int edge[110][110];
 7 int dis[110];    //頂點i到最小生成樹頂點集合的最短距離
 8 int vis[110];
 9 void prime()
10 {
11     ans = 0;
12     for(int i = 1; i <= n; i++)
13         dis[i] = edge[1][i];
14     dis[1] = 0;
15     vis[1] = 1;
16     for(int k = 2; k <= n; k++)
17     {
18         int minn = INF;    //須要加入的邊權
19         int pos;    //要加入的頂點序號
20         for(int i = 1; i <= n; i++)
21         {
22             if(!vis[i] && dis[i] < minn)
23             {
24                 minn = dis[i];
25                 pos = i;
26             }
27         }
28         if(minn == INF)    //不是連通圖
29             break;
30         vis[pos] = 1;
31         ans += minn;
32         for(int i = 1; i <= n; i++)
33         {
34             if(!vis[i] && dis[i] > edge[pos][i])
35             {
36                 dis[i] = edge[pos][i];
37             }
38         }
39     }
40 }
41 
42 int main()
43 {
44     int s, e, w;
45     while(cin >> n && n)
46     {
47         memset(vis, 0, sizeof(vis));
48         int m = n * (n - 1) / 2;
49         for(int i = 1; i <= m; i++)
50         {
51             cin >> s >> e >> w;
52             edge[s][e] = edge[e][s] = w;    //無向圖
53         }
54         prime();
55         cout << ans << endl;
56     }
57     return 0;
58 }

 

kruskal寫法:

 1 #include<iostream>
 2 #include<algorithm>
 3 using namespace std;
 4 const int maxn = 1e4 + 10;
 5 int n, m, ans;
 6 int far[maxn];
 7 struct node
 8 {
 9     int s, e, w;
10 } edge[maxn];
11 bool cmp(node a, node b)
12 {
13     return a.w < b.w;
14 }
15 int find(int x)
16 {
17     return (far[x] == x) ? far[x] : (far[x] = find(far[x]));
18 }
19 void unite(int x, int y)
20 {
21     int xx = find(x);
22     int yy = find(y);
23     if(xx != yy)
24         far[yy] = xx;
25 }
26 void kruskal()
27 {
28     ans = 0;
29     sort(edge, edge + m, cmp);
30     for(int i = 0; i <= n; i++)
31         far[i] = i;
32     for(int i = 0; i < m; i++)
33     {
34         int xx = find(edge[i].s);
35         int yy = find(edge[i].e);
36         if(xx != yy)
37         {
38             unite(edge[i].s, edge[i].e);
39             ans += edge[i].w;
40         }
41     }
42 }
43 int main()
44 {
45     while(cin >> n && n)
46     {
47         m = n * (n - 1) / 2;
48         for(int i = 0; i < m; i++)
49         {
50             cin >> edge[i].s >> edge[i].e >> edge[i].w;
51         }
52         kruskal();
53         cout << ans << endl;
54     }
55     return 0;
56 }
相關文章
相關標籤/搜索