1. 程式人生 > >wenbao與最小生成樹

wenbao與最小生成樹

val color \n AS spl memset 隊列優化 display esp

----------------------------------------------------------

Kruskal模板

 1 const int maxn = 105;
 2 int n, m, u[maxn], v[maxn], w[maxn], r[maxn], p[maxn];
 3 
 4 int cmp(const int i, const int j) { 
 5     return w[i] < w[j];
 6 }
 7 
 8 int findn(int x) {
 9     return p[x] == x ? x : p[x] = findn(p[x]);
10 } 11 12 int Kruskal() { 13 int ans = 0, num = 0; 14 for(int i = 1; i <= m; ++i) p[i] = i; 15 sort(r, r+n, cmp); 16 for(int i = 0; i < n; i++) { 17 int e = r[i]; 18 int x = findn(u[e]), y = findn(v[e]); 19 if(x != y) { 20 num ++; 21 ans += w[e];
22 p[x] = y; 23 } 24 } 25 if(num != m-1) printf("?\n"); 26 else printf("%d\n", ans); 27 }

離散課本實現

 1 #include <iostream>
 2 #include <algorithm>
 3 using namespace std;
 4 struct Node{
 5     int v, vv, w;
 6 }T[20];
 7 int cmp(Node a, Node b){
8 return a.w < b.w; 9 } 10 int TT[20]; 11 int Find(int x){ 12 return TT[x] == x ? x : TT[x] = Find(TT[x]); 13 } 14 void kru(int x){ 15 for(int i = 0; i <= x; i++){ 16 TT[i] = i; 17 } 18 int sum = 0; 19 sort(T, T+x, cmp); 20 for(int i = 0; i < x; i++){ 21 int xx = Find(T[i].v); 22 int yy = Find(T[i].vv); 23 if(xx != yy){ 24 sum += T[i].w; 25 TT[xx] = yy; 26 } 27 } 28 printf("%d\n", sum); 29 } 30 int main(){ 31 int n; 32 scanf("%d", &n); 33 for(int i = 0; i < n; i++){ 34 scanf("%d%d%d", &T[i].v, &T[i].vv, &T[i].w); 35 } 36 kru(n); 37 }

-------------------------------------------------------------------------

prim

鄰接表優化

 1 int head[111], Next[222], point[222], val[222], size, dist[111];
 2 int n, m, x, y, z;
 3 
 4 void add (int a, int b, int v) {
 5     int i;
 6     for(i = head[a]; ~i; i = Next[i]) {
 7         if(point[i] == b) {
 8             if(val[i] > v) val[i] = v;
 9             return;
10         }
11     }
12     point[size] = b;
13     val[size] = v;
14     Next[size] = head[a];
15     head[a] = size++;
16 }
17 
18 void prim() {   //prim函數,傳入圖中一點
19     memset(dist, 0x3f3f, sizeof(dist));
20     for(int i = head[1]; ~i; i = Next[i]){
21         dist[point[i]] = val[i];
22     }
23     dist[1] = -1;
24     int sum = 0;
25     for(int i = 2; i <= m; ++i){
26         int mi = 1e9, k = -1;
27         for(int j = 2; j <= m; ++j){
28             if(dist[j] != -1 && dist[j] < mi){
29                 mi = dist[j], k = j;
30             }
31         }
32         if(k == -1){
33             printf("?\n");
34             return ;
35         }
36         dist[k] = -1;
37         sum += mi;
38         for(int j = head[k]; ~j; j = Next[j]){
39             if(dist[point[j]] != -1 && dist[point[j]] > val[j]){
40                 dist[point[j]] = val[j];
41             }
42         }
43     }
44     printf("%d\n", sum);
45 }

鄰接表優先隊列優化

 1 typedef pair<int,int> pii;
 2 
 3 int head[30], next[200], point[200], val[200], size, dist[30];
 4 
 5 void add (int a, int b, int v) {   //加邊及去重
 6     int i;
 7     for(i = head[a]; ~i; i = next[i]) {
 8         if(point[i] == b) {
 9             if(val[i] > v) val[i] = v;
10             return;
11         }
12     }
13     point[size] = b;
14     val[size] = v;
15     next[size] = head[a];
16     head[a] = size++;
17 }
18 
19 struct cmp {   //重載小根堆
20     bool operator()(pii a, pii b) {
21         return a.first > b.first;
22     }
23 };
24 
25 void prim(int s) {   //prim函數,傳入圖中一點
26     int i, ans = 0;
27     memset(dist, 0x3f, sizeof(dist));
28     priority_queue<pii, vector<pii>, cmp>q;
29     for (i = head[s]; ~i; i = next[i]) {
30         dist[point[i]] = val[i];
31         q.push(make_pair(dist[point[i]], point[i]));
32     }
33     dist[s] = -1;
34     while(!q.empty()) {
35         pii u = q.top();
36         q.pop();
37         if(dist[u.second] == -1) continue;
38         dist[u.second] = -1;
39         ans += u.first;
40         for(i = head[u.second]; ~i; i = next[i]) {
41             int j = point[i];
42             if(dist[j] > val[i]) {
43                 dist[j] = val[i];
44                 q.push(make_pair(dist[j], j));
45             }
46         }
47     }
48     printf("%d\n", ans);
49 }

---------------------------------------------------------------------------

http://acm.hdu.edu.cn/showproblem.php?pid=1863

prim

 1 #include "iostream"
 2 #include <algorithm>
 3 #include <string.h>
 4 #include <queue>
 5 #include <stdio.h>
 6 using namespace std;
 7 typedef pair<int,int> pii;
 8 
 9 int head[111], Next[222], point[222], val[222], size, dist[111];
10 bool vis[111];
11 int n, m, x, y, z;
12 
13 void add (int a, int b, int v) {   //加邊及去重
14     int i;
15     for(i = head[a]; ~i; i = Next[i]) {
16         if(point[i] == b) {
17             if(val[i] > v) val[i] = v;
18             return;
19         }
20     }
21     point[size] = b;
22     val[size] = v;
23     Next[size] = head[a];
24     head[a] = size++;
25 }
26 
27 struct cmp {   //重載小根堆
28     bool operator()(pii a, pii b) {
29         return a.first > b.first;
30     }
31 };
32 
33 void prim(int s) {   //prim函數,傳入圖中一點
34     int i, ans = 0, num = 0;
35     memset(dist, -1, sizeof(dist));
36     memset(vis, 0, sizeof(vis));
37     priority_queue<pii, vector<pii>, cmp>q;
38     for (i = head[s]; ~i; i = Next[i]) {
39         dist[point[i]] = val[i];
40         q.push(make_pair(dist[point[i]], point[i]));
41     }
42     dist[s] = 0;
43     vis[s] = 1;
44     while(!q.empty()) {
45         pii u = q.top();
46         q.pop();
47         if(vis[u.second]) continue;
48         vis[u.second] = 1;
49         ans += u.first;
50         num++;
51         for(i = head[u.second]; ~i; i = Next[i]) {
52             int j = point[i];
53             if(!vis[j] && (dist[j] > val[i] || dist[j] == -1)) {
54                 dist[j] = val[i];
55                 q.push(make_pair(dist[j], j));
56             }
57         }
58     }
59     if(num != m-1) printf("?\n");
60     else printf("%d\n", ans);
61 }
62 
63 int main(){
64 #ifdef wenbao
65     freopen("in", "r", stdin);
66 #endif
67     while(~scanf("%d%d", &n, &m)){
68         if(n == 0) break;
69         size = 0;
70         memset(head, -1, sizeof(head));
71         for(int i = 0; i < n; ++i){
72             scanf("%d%d%d", &x, &y, &z);
73             add(x, y, z), add(y, x, z);
74         }
75         prim(1);
76     }
77     return 0;
78 }

Kruskal

 1 #include "iostream"
 2 #include <algorithm>
 3 using namespace std;
 4 
 5 const int maxn = 105;
 6 int n, m, u[maxn], v[maxn], w[maxn], r[maxn], p[maxn];
 7 
 8 int cmp(const int i, const int j) { 
 9     return w[i] < w[j];
10 }
11 
12 int findn(int x) {
13     return p[x] == x ? x : p[x] = findn(p[x]);
14 }
15 
16 int Kruskal() {
17     int ans = 0, num = 0;
18     for(int i = 1; i <= m; ++i) p[i] = i;
19     sort(r, r+n, cmp);
20     for(int i = 0; i < n; i++) {
21         int e = r[i];
22         int x = findn(u[e]);
23         int y = findn(v[e]);
24         if(x != y) {
25             num ++;
26             ans += w[e];
27             p[x] = y;
28         }
29     }
30     if(num != m-1) printf("?\n");
31     else printf("%d\n", ans);
32 }
33 
34 int main() {
35 #ifdef wenbao
36     freopen("in", "r", stdin);
37 #endif
38     while(~scanf("%d%d", &n, &m)){
39         if(n == 0) break;
40         for(int i = 0; i < n; ++i){
41             scanf("%d%d%d", &u[i], &v[i], &w[i]), r[i] = i;
42         }
43         Kruskal();
44     }
45     return 0;
46 }

---------------------------------------------------------------------------

只有不斷學習才能進步!

wenbao與最小生成樹