【问题描述】
已知含有n个顶点的带权连通无向图,采用邻接矩阵存储,邻接矩阵以三元组的形式给出,
只给出不包括主对角线元素在内的下三角形部分的元素,且不包括不相邻的顶点对。求该连通图的最小生成树中各边的权值之和。
注:三元组来表一条带权的边,如2 1 7表示顶点2到顶点1的边的权值为7.
【输入形式】
第一行给出结点个数n和三元组的个数count,以下每行给出一个三元组,数之间用空格隔开。
(注意这里顶点的序号是从1到n,而不是0到n-1,程序里要小心!)
【输出形式】
最小生成树的权值
【样例输入】
5 8
2 1 7
3 1 6
3 2 8
4 1 9
4 2 4
4 3 6
5 2 4
5 4 2
【样例输出】
18
【样例说明】
权值是正整数,可能很大,但不需要考虑整型溢出问题
C++代码
#include<iostream>
using namespace std;
struct edgenode {
int begin, end, weight; //定义边的两个邻接点、权重
};
int Find(int fathers[], int n) { //找父亲函数
int f = n;
while (fathers[f] > 0)
f = fathers[f];
return f;
}
void CreateEdge(edgenode*& node) {
node = new edgenode;
cin >> node->begin >> node->end >> node->weight; //录入两个临界点的序号及边权重
}
void Sort(edgenode* edgelist[], int e) { //按边权值由小到大排序
for (int i = 0; i < e; i++)
for (int j = 0; j < e - i - 1; j++)
if (edgelist[j]->weight > edgelist[j + 1]->weight)
swap(edgelist[j], edgelist[j + 1]);
}
void Kruskal(edgenode* edgelist[], int e, int& cnt) { //Kruskal算法
int fathers[1000];
for (int i = 0; i < e; i++)
fathers[i] = 0;
int bgf, edf; //bgf=begin's father, edf=end's father
for (int i = 0; i < e; i++) {
bgf = Find(fathers, edgelist[i]->begin);
edf = Find(fathers, edgelist[i]->end);
if (bgf != edf) { //判断是否为一个连通分量
fathers[edf] = bgf; //若不为一个,则把两个连通分量归并为一个
//cout << "(" << edgelist[i]->begin << "," << edgelist[i]->end << ")" << endl;
cnt += edgelist[i]->weight; //存放权值
}
}
}
int main() {
edgenode* edgelist[1000];
int n, e; //n=nodes' count, e=edges' count
cin >> n >> e; //输入点、边数量
for (int i = 0; i < e; i++)
CreateEdge(edgelist[i]); //初始化边表数组
Sort(edgelist, e); //排序
int cnt = 0; //存放权值
Kruskal(edgelist, e, cnt);
cout << cnt << endl;
return 0;
}