Prim和Kruskal最小生成树

Posted Penn000

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Prim和Kruskal最小生成树相关的知识,希望对你有一定的参考价值。

标题: Prim和Kruskal最小生成树
时 限: 2000 ms
内存限制: 15000 K
总时限: 3000 ms
描述: 给出一个矩阵,要求以矩阵方式单步输出生成过程。
要求先输出Prim生成过程,再输出Kruskal,每个矩阵输出后换行。
注意,题中矩阵表示无向图
输入: 结点数
矩阵
输出: Prim:
矩阵输出
Kruskal:
矩阵输出
输入样例:
3

0 1 3

1 0 2

3 2 0

 

输出样例:
3


0 1 3

1 0 2

3 2 0
Prim:

0 0 0

0 0 0

0 0 0

 

0 1 0

1 0 0

0 0 0

 

0 1 0

1 0 2

0 2 0

 

Kruskal:

0 0 0

0 0 0

0 0 0

 

0 1 0

1 0 0

0 0 0

 

0 1 0

1 0 2

0 2 0

提示: Kruskal 中的边集合应用拓扑排序的想法排除环
来源: 教材P170-179

  1 //2016.10.25
  2 #include <iostream>
  3 #include <cstdio>
  4 #include <cstring>
  5 #include <algorithm>
  6 #define N 200
  7 
  8 using namespace std;
  9 
 10 struct Edge
 11 {
 12     int u, v, c;
 13     bool operator<(Edge x){
 14         return c < x.c;
 15     }
 16 }edge[100005];
 17 int G[N][N], T[N][N], n, cnt, fa[N];
 18 
 19 void print(int T[][N])
 20 {
 21     for(int i = 1; i <= n; i++){
 22         for(int j = 1; j <= n; j++){
 23             printf("%d ", T[i][j]);
 24         }
 25         printf("\n");
 26     }
 27     printf("\n");
 28 }
 29 
 30 void init(int n)
 31 {
 32     for(int i = 1; i <= n; i++)
 33           fa[i] = i;
 34 }
 35 
 36 int getfa(int x)
 37 {
 38     if(fa[x] == x) return x;
 39     return fa[x] = getfa(fa[x]);
 40 }
 41 
 42 void myUnion(int a, int b)
 43 {
 44     int af = getfa(a);
 45     int bf = getfa(b);
 46     if(af != bf)fa[bf] = af;
 47 }
 48 
 49 void prim()
 50 {
 51     int book[N], uf, vf;
 52     memset(T, 0, sizeof(T));
 53     memset(book, 0, sizeof(book));
 54     print(T);
 55     sort(edge, edge+cnt);
 56     init(n);
 57     int cntv = 1;
 58     int parent = edge[0].u;
 59     while(cntv < n)
 60     {
 61         for(int i = 0; i < cnt; i++)
 62         {
 63             if(book[i])continue;
 64             uf = getfa(edge[i].u);
 65             vf = getfa(edge[i].v);
 66             if((uf == parent || vf == parent) && uf != vf)
 67             {
 68                 myUnion(parent, uf);
 69                 myUnion(parent, vf);
 70                 book[i] = 1;
 71                 T[edge[i].u][edge[i].v] = T[edge[i].v][edge[i].u] = edge[i].c;
 72                 print(T);
 73                 cntv++;
 74                 break;
 75             }
 76         }
 77     }
 78     return ;
 79 }
 80 
 81 void kruskal()
 82 {
 83     sort(edge, edge+cnt);
 84     int book[N], uf, vf;
 85     init(n);
 86     memset(book, 0, sizeof(book));
 87     memset(T, 0, sizeof(T));
 88     print(T);
 89     for(int i = 0; i < cnt; i++)
 90     {
 91         uf = getfa(edge[i].u);
 92         vf = getfa(edge[i].v);
 93         if(uf != vf)
 94         {
 95             T[edge[i].u][edge[i].v] = T[edge[i].v][edge[i].u] = edge[i].c;
 96             myUnion(edge[i].u, edge[i].v);
 97             book[edge[i].u] = book[edge[i].v] = 1;
 98             print(T);
 99         }
100         int sum = 0;
101         for(int i = 1; i <= n; i++){
102             if(fa[i] == i)sum++;
103             if(sum > 1)break;
104         }
105         if(sum==1)break;
106     }
107     return;
108 }
109 
110 int main()
111 {
112     cnt = 0;
113     scanf("%d", &n);
114     for(int i = 1; i <= n; i++)
115           for(int j = 1; j <= n; j++)
116           {
117               scanf("%d", &G[i][j]);
118               if(i < j && G[i][j] != 0)
119               {
120                   edge[cnt].u = i;
121                   edge[cnt].v = j;
122                   edge[cnt].c = G[i][j];
123                   cnt++;
124               }
125           }
126     printf("Prim:\n");
127     prim();
128     printf("Kruskal:\n");
129     kruskal();
130 
131     return 0;
132 }

 

以上是关于Prim和Kruskal最小生成树的主要内容,如果未能解决你的问题,请参考以下文章

图解:如何实现最小生成树(Prim算法与Kruskal算法)

Prim和Kruskal最小生成树

关于最小生成树的Prim算法和Kruskal算法

最小生成树及Prim算法及Kruskal算法的代码实现

最小生成树之Kruskal算法和Prim算法

图的最小生成树算法(Prim和Kruskal)