无向图最小生成树(prim算法)

普里姆算法Prim算法),图论中的一种算法,可在加权连通图里搜索最小生成树。意即由此算法搜索到的边子集所构成的树中,不但包括了连通图里的所有顶点,且其所有边的权值之和亦为最小。该算法于1930年由捷克数学家沃伊捷赫·亚尔尼克发现;并在1957年由美国计算机科学家罗伯特·普里姆独立发现;1959年,艾兹格·迪科斯彻再次发现了该算法。因此,在某些场合,普里姆算法又被称为DJP算法亚尔尼克算法普里姆-亚尔尼克算法

算法过程图解:遍历点,用贪心法选择与集合内的点相连的点的最小值;

 模板:

 1 #include <iostream>
 2 #include <algorithm>
 3 #include <cmath>
 4 #include <cstdio>
 5 #include <string>
 6 #include <cstring>
 7 #include <vector>
 8 #include <queue>
 9 #include <stack>
10  #include <set>
11  #define INF 0x3f3f3f3f
12  #define INFL 0x3f3f3f3f3f3f3f3f
13  #define zero_(x,y) memset(x , y , sizeof(x))
14  #define zero(x) memset(x , 0 , sizeof(x))
15  #define MAX(x) memset(x , 0x3f ,sizeof(x))
16  using namespace std;
17  #define N 1005
18  typedef long long LL ;
19  int G[N][N];
20  int minn[N];///寻找最小权;
21  bool point[N];
22 
23  int main(){
24      //freopen("in.txt","r",stdin);
25      memset(point, 0, sizeof(point));
26      int n, m, x, y, ans=0;
27      scanf("%d%d", &n, &m);
28      for(int i=1;i<=n;i++){
29          for(int j = 1; j <= n; j++){
30              G[i][j] = INF;
31          }
32      }
33      for(int i = 1; i <= m; i++) {
34          scanf("%d%d", &x, &y);
35          scanf("%d", &G[x][y]);
36          G[y][x] = G[x][y];
37      }
38      point[1] = true;
39      for(int i = 1;i <= n; i++) minn[i] = G[1][i];
40      for(int i = 1 ; i <= n; i++){
41          int k = 0, mi = INF;
42          for(int j = 1; j <= n; j++){
43              if(!point[j] && minn[j] < mi){
44                  mi = minn[j];
45                  k = j;
46              }
47          }
48          ans += minn[k];
49          point[k] = true;
50          for(int s = 1;s <= n; s++){
51              if(!point[s] && G[k][s] < minn[s])///保存了之前没有加入集合的边的权;
52                  minn[s] = G[k][s];
53          }
54      }
55      printf("%d\n", ans);
56      return 0;
57  }
View Code

 

poj 1789

题意:点是7位小写字母,边是小写字母间的不同字母数量(1-7)。求最小生成树。

边权:the number of positions with different letters in truck type codes.

 

 1 #include <iostream>
 2 #include <algorithm>
 3 #include <stdlib.h>
 4 #include <time.h>
 5 #include <cmath>
 6 #include <cstdio>
 7 #include <string>
 8 #include <cstring>
 9 #include <vector>
10 #include <queue>
11 #include <stack>
12 #include <set>
13 
14 #define c_false ios_base::sync_with_stdio(false); cin.tie(0)
15 #define INF 0x3f3f3f3f
16 #define INFL 0x3f3f3f3f3f3f3f3f
17 #define zero_(x,y) memset(x , y , sizeof(x))
18 #define zero(x) memset(x , 0 , sizeof(x))
19 #define MAX(x) memset(x , 0x3f ,sizeof(x))
20 #define swa(x,y) {LL s;s=x;x=y;y=s;}
21 using namespace std ;
22 #define N 2005
23 
24 const double PI = acos(-1.0);
25 typedef long long LL ;
26 int n, dis[N][N], minn[N];
27 char x[10];
28 string type[N];
29 bool point[N];
30 
31 int Distance(int i, int j){
32     int len = 7, sum = 0;
33     for(int k = 0; k < len; k++)
34         if(type[i][k] != type[j][k])
35             sum++;
36     return sum;
37 }
38 int prim(){
39     point[1] = true;
40     int ans = 0;
41     for(int i = 1; i <= n; i++) minn[i] = dis[1][i];
42     for(int i = 1; i <= n; i++){
43         int k = 0; int mi =INF;
44         for(int j = 1; j <= n; j++){
45             if(!point[j] && minn[j] <mi){
46                 mi = minn[j];
47                 k = j;
48             }
49         }
50         ans += minn[k];
51         point[k] = true;
52         for(int s = 1; s <= n; s++){
53             if(!point[s] && dis[k][s] <minn[s])
54                 minn[s] = dis[k][s];
55         }
56     }
57     return ans;
58 }
59 int main(){
60     //freopen("in.txt","r",stdin);
61     //freopen("out.txt","w",stdout);
62     //ios_base::sync_with_stdio(false); cin.tie(0);
63     while(~scanf("%d", &n) && n){
64         zero(dis);zero(point);MAX(dis);
65         for(int i = 1; i <= n; i++){
66             scanf("%s", x);
67             type[i] = x;
68         }
69         for(int i = 1; i<= n; i++){
70             for(int j = 1; j < i; j++){
71                 dis[i][j] = dis[j][i] = Distance(i, j);
72             }
73         }
74         printf("The highest possible quality is 1/%d.\n", prim());
75     }
76     return 0;
77 }
View Code

 

poj 2485

题意:求最小生成树的最大边权;(英语实在太烂)

 point:minimize the length of the longest highway

 1 #include <iostream>
 2 #include <algorithm>
 3 #include <stdlib.h>
 4 #include <time.h>
 5 #include <cmath>
 6 #include <cstdio>
 7 #include <string>
 8 #include <cstring>
 9 #include <vector>
10 #include <queue>
11 #include <stack>
12 #include <set>
13 
14 #define c_false ios_base::sync_with_stdio(false); cin.tie(0)
15 #define INF 0x3f3f3f3f
16 #define INFL 0x3f3f3f3f3f3f3f3f
17 #define zero_(x,y) memset(x , y , sizeof(x))
18 #define zero(x) memset(x , 0 , sizeof(x))
19 #define MAX(x) memset(x , 0x3f ,sizeof(x))
20 #define swa(x,y) {LL s;s=x;x=y;y=s;}
21 using namespace std ;
22 #define N 505
23 
24 const double PI = acos(-1.0);
25 typedef long long LL ;
26 int T, n, dis[N][N], minn[N];
27 bool point[N];
28 
29 int prim(){
30     point[1] = true;
31     int ans = 0;
32     for(int i = 1; i <= n; i++) minn[i] = dis[1][i];
33     for(int i = 1; i <= n; i++){
34         int k = 0; int mi =INF;
35         for(int j = 1; j <= n; j++){
36             if(!point[j] && minn[j] <mi){
37                 mi = minn[j];
38                 k = j;
39             }
40         }
41         if(ans < minn[k]) ans = minn[k];
42         point[k] = true;
43         for(int s = 1; s <= n; s++){
44             if(!point[s] && dis[k][s] <minn[s])
45                 minn[s] = dis[k][s];
46         }
47     }
48     return ans;
49 }
50 
51 int main(){
52     //freopen("in.txt","r",stdin);
53     //freopen("out.txt","w",stdout);
54     //ios_base::sync_with_stdio(false); cin.tie(0);
55     scanf("%d", &T);
56     while(T--){
57         zero(point);zero(dis);zero(minn);
58         scanf("%d", &n);
59         for(int i = 1; i <= n; i++){
60             for(int j = 1; j <= n; j++){
61                 scanf("%d", &dis[i][j]);
62             }
63         }
64         printf("%d\n", prim());
65     }
66     return 0;
67 }
View Code

 

poj 1258

简单模板题,同上;

 1 #include <iostream>
 2 #include <algorithm>
 3 #include <stdlib.h>
 4 #include <time.h>
 5 #include <cmath>
 6 #include <cstdio>
 7 #include <string>
 8 #include <cstring>
 9 #include <vector>
10 #include <queue>
11 #include <stack>
12 #include <set>
13 
14 #define c_false ios_base::sync_with_stdio(false); cin.tie(0)
15 #define INF 0x3f3f3f3f
16 #define INFL 0x3f3f3f3f3f3f3f3f
17 #define zero_(x,y) memset(x , y , sizeof(x))
18 #define zero(x) memset(x , 0 , sizeof(x))
19 #define MAX(x) memset(x , 0x3f ,sizeof(x))
20 #define swa(x,y) {LL s;s=x;x=y;y=s;}
21 using namespace std ;
22 #define N 505
23 
24 const double PI = acos(-1.0);
25 typedef long long LL ;
26 int n, dis[N][N], minn[N];
27 bool point[N];
28 
29 int prim(){
30     point[1] = true;
31     int ans = 0;
32     zero(minn);zero(point);
33     for(int i = 1; i <= n; i++) minn[i] = dis[1][i];
34     for(int i = 1; i <= n; i++){
35         int k = 0; int mi =INF;
36         for(int j = 1; j <= n; j++){
37             if(!point[j] && minn[j] <mi){
38                 mi = minn[j];
39                 k = j;
40             }
41         }
42         ans += minn[k];
43         point[k] = true;
44         for(int s = 1; s <= n; s++){
45             if(!point[s] && dis[k][s] <minn[s])
46                 minn[s] = dis[k][s];
47         }
48     }
49     return ans;
50 }
51 
52 int main(){
53     //freopen("in.txt","r",stdin);
54     //freopen("out.txt","w",stdout);
55     //ios_base::sync_with_stdio(false); cin.tie(0);
56     while(~scanf("%d", &n) && n){
57         zero(dis);
58         for(int i = 1; i <= n; i++){
59             for(int j = 1; j <= n; j++){
60                 scanf("%d", &dis[i][j]);
61             }
62         }
63         printf("%d\n", prim());
64     }
65     return 0;
66 }
View Code

 

poj 3026

题意:求最小生成树;

思路:prim + BFS

   这题的难点在于寻找邻接矩阵;

    用BFS 找到各点间的最小距离的点;

      然后就是套模板;

 

转载于:https://www.cnblogs.com/yoyo-sincerely/p/5191410.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值