本文采用kruskal法解决求最小生成树的各边权值和(从边集出发对各边按权值排序(冒泡排序)),排序也可以采用更高效的快排。
Description |
根据输入构建无向带权图,并利用kruskal法求出最小生成树,输出该最小生成树的各边权值和。 输入: 第一行为:结点数; 第二行为各结点名;第三行为各边的权值。 输出:最小生成树的各边权值和。 |
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 1005
#define Maxint 32767
using namespace std;
//邻接表的存储结构
typedef struct Arcnode
{
int adjvex;
};
typedef struct Vnode
{
char data;
} Vnode, Adjlist[Maxnum];
typedef struct edgenode
{ // 边集存储结构
int vex1, vex2;
int info;//权值
} edgenode;
typedef struct
{
edgenode *edgelist;//边集组
int edgenum;//边数
Adjlist verices;
int vex, arc;
} ALG;
int locatevex(ALG G, char v)
{//查找下标
int i;
for (int i = 0; i < G.vex; i++)
{
if (v == G.verices[i].data)
{
return i;
}
}
}
void creatALG(ALG &G)
{//无向带权图
cin >> G.vex;
// G.edgenum=G.arc;
G.edgelist = new edgenode[Maxnum];
char v1, v2;
int in;
for (int i = 0; i < G.vex; i++)
{
cin >> G.verices[i].data;
}
int m = 0;
while (cin >> v1 >> v2 >> in)
{
int i = locatevex(G, v1);
int j = locatevex(G, v2);
G.edgelist[m].vex1 = i;//记录每个边结点的下标
G.edgelist[m].vex2 = j;
G.edgelist[m].info = in;
m++;
}
G.edgenum = m;
}
typedef struct MSTEdge
{
int vex1, vex2; /* 边所依附的图中两个顶点*/
int weight; /* 边的权值*/
} MSTEdge;
void sort(ALG &G)
{//对结构按权值从小到大进行排序(冒泡排序)
for (int i = 1; i <= G.edgenum - 1; i++)
{
for (int j = G.edgenum - 1; j > i - 1; j--)
{
if (G.edgelist[j].info < G.edgelist[j - 1].info)
{
ALG tmp;
tmp.edgelist = new edgenode[Maxnum];
tmp.edgelist[0] = G.edgelist[j];//交换
G.edgelist[j] = G.edgelist[j - 1];
G.edgelist[j - 1] = tmp.edgelist[0];
}
}
}
}
void Kruskal_MST(ALG &G, int &cnt) /* 用Kruskal算法构造图G的最小生成树*/
{
MSTEdge TE[Maxnum];//最小生成树的存储结构
int j, k, v, s1, s2, Vset[Maxnum];//vest辅助数组用于判断是否出现回路
int w;
for (j = 0; j < G.vex; j++)
Vset[j] = j; /* 初始化数组Vset[n] */
sort(G); /* 对表按权值从小到大排序*/
j = 0;
k = 0;
while (k < G.vex - 1 && j < G.edgenum)
{//遍历n-1个结点,并且小于边数
s1 = Vset[G.edgelist[j].vex1];
s2 = Vset[G.edgelist[j].vex2]; /* 若边的两个顶点的连通分量编号不同, 边加入到TE中*/
if (s1 != s2)
{//相同则代表出现回路
TE[k].vex1 = G.edgelist[j].vex1;
TE[k].vex2 = G.edgelist[j].vex2;
TE[k].weight = G.edgelist[j].info;
cnt += G.edgelist[j].info;//记录各边权值和
k++;//结点数加一
}
for (v = 0; v < G.vex; v++)
{//更新辅助数组(把出现的结点值设成一致)
if (Vset[v] == s2)
Vset[v] = s1;
}
j++;//边加一
}
}
int main()
{
ALG G;
creatALG(G);
int cnt = 0;//记录最小生成树权值和
Kruskal_MST(G, cnt);
cout << cnt << "\n";
return 0;
}