注:本文根据普里姆算法的自拟题目,和数据结构-带权无向图-最小生成树(克鲁斯卡尔算法)-CSDN博客类似
Description
根据输入构建无向带权图,并利用普里姆法求出最小生成树,输出该最小生成树的各边权值和。
输入:
第一行为:结点数; 第二行为各结点名;第三行为各边的权值。
输出:最小生成树的各边权值和。
Sample Input
5
A B C D E
A B 10
A C 8
A E 3
B C 2
B D 5
C E 7
D E 4
Sample Output
14
Hint
输出有换行符。
#include <bits/stdc++.h>
#define Maxnum 10
#define Maxint 32576
using namespace std;
typedef struct Arcnode
{
int adj;
} adjlist[Maxnum][Maxnum];
typedef struct Vnode
{
char vexs[Maxnum];
adjlist arcs;
int vex, arc;
} MG;
typedef struct node
{
char adjvex;
int lowcost;
} node, closedge[Maxnum];
int locatevex(MG G, char v)
{ // 查找下标
int i;
for (int i = 0; i < G.vex; i++)
{
if (v == G.vexs[i])
{
return i;
}
}
}
void creatMG(MG &G)
{
cin >> G.vex;
char v1, v2;
int in;
for (int i = 0; i < G.vex; i++)
{
cin >> G.vexs[i];
for (int j = 0; j < G.vex; j++)
{
G.arcs[i][j].adj = Maxint;
}
}
while (cin >> v1 >> v2 >> in)
{
int i = locatevex(G, v1);
int j = locatevex(G, v2);
G.arcs[i][j].adj = in;
G.arcs[j][i].adj = in; // 记录每个边结点的下标
}
}
int Find(closedge close, int n)
{
int min = Maxint, k;
for (int i = 0; i < n; i++)
{
if (close[i].lowcost < min && close[i].lowcost != 0)
{
min = close[i].lowcost;
k = i;
}
}
return k;
}
void PLM_MST(MG G, int &cnt)
{ // 默认从0顶点开始出发
int i, j, k = 0;
closedge close;
for (j = 0; j < G.vex; j++)
{ // 初始化辅助数组
if (j != k)
{ // 与k相邻的为权值,其他为最大值
close[j].adjvex = '\0';
close[j].lowcost = G.arcs[k][j].adj;
}
}
close[k].lowcost = 0;
for (i = 1; i < G.vex; i++)
{
k = Find(close, G.vex); // 查找未被标记中权值最小的结点(防止出现回路)
cnt += close[k].lowcost; // 记录权值和
close[k].lowcost = 0; // 标记
for (j = 0; j < G.vex; j++) // 更新辅助数组的值
{
if (G.arcs[k][j].adj < close[j].lowcost)
{ // 此时与k相邻比记录的小就更新
close[j].adjvex = G.vexs[k];
close[j].lowcost = G.arcs[k][j].adj;
}
}
}
}
int main()
{
MG G;
creatMG(G);
int cnt = 0; // 记录最小生成树权值和
PLM_MST(G, cnt);
cout << cnt << "\n";
return 0;
}