Bootstrap

用kruskal算法求最小生成树各边的权值之和

【问题描述】

已知含有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

【样例说明】

权值是正整数,可能很大,但不需要考虑整型溢出问题

cg

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;
}
;