标题: 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
//2016.10.25
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define N 200 using namespace std; struct Edge
{
int u, v, c;
bool operator<(Edge x){
return c < x.c;
}
}edge[];
int G[N][N], T[N][N], n, cnt, fa[N]; void print(int T[][N])
{
for(int i = ; i <= n; i++){
for(int j = ; j <= n; j++){
printf("%d ", T[i][j]);
}
printf("\n");
}
printf("\n");
} void init(int n)
{
for(int i = ; i <= n; i++)
fa[i] = i;
} int getfa(int x)
{
if(fa[x] == x) return x;
return fa[x] = getfa(fa[x]);
} void myUnion(int a, int b)
{
int af = getfa(a);
int bf = getfa(b);
if(af != bf)fa[bf] = af;
} void prim()
{
int book[N], uf, vf;
memset(T, , sizeof(T));
memset(book, , sizeof(book));
print(T);
sort(edge, edge+cnt);
init(n);
int cntv = ;
int parent = edge[].u;
while(cntv < n)
{
for(int i = ; i < cnt; i++)
{
if(book[i])continue;
uf = getfa(edge[i].u);
vf = getfa(edge[i].v);
if((uf == parent || vf == parent) && uf != vf)
{
myUnion(parent, uf);
myUnion(parent, vf);
book[i] = ;
T[edge[i].u][edge[i].v] = T[edge[i].v][edge[i].u] = edge[i].c;
print(T);
cntv++;
break;
}
}
}
return ;
} void kruskal()
{
sort(edge, edge+cnt);
int book[N], uf, vf;
init(n);
memset(book, , sizeof(book));
memset(T, , sizeof(T));
print(T);
for(int i = ; i < cnt; i++)
{
uf = getfa(edge[i].u);
vf = getfa(edge[i].v);
if(uf != vf)
{
T[edge[i].u][edge[i].v] = T[edge[i].v][edge[i].u] = edge[i].c;
myUnion(edge[i].u, edge[i].v);
book[edge[i].u] = book[edge[i].v] = ;
print(T);
}
int sum = ;
for(int i = ; i <= n; i++){
if(fa[i] == i)sum++;
if(sum > )break;
}
if(sum==)break;
}
return;
} int main()
{
cnt = ;
scanf("%d", &n);
for(int i = ; i <= n; i++)
for(int j = ; j <= n; j++)
{
scanf("%d", &G[i][j]);
if(i < j && G[i][j] != )
{
edge[cnt].u = i;
edge[cnt].v = j;
edge[cnt].c = G[i][j];
cnt++;
}
}
printf("Prim:\n");
prim();
printf("Kruskal:\n");
kruskal(); return ;
}