标签:
并查集有很多经典的应用。在一些有N个元素的集合应用问题中,我们通常是在开始时让每个元素构成一个单元素的集合,然后按一定顺序将属于同一组的元素所在的集合合并,其间要反复查找一个元素在哪个集合中。kruskal算法是一个贪心算法,把所有的边按权值从小到大依次考虑,如果当前边加进生成树中会出现回路,则丢弃当前边,否则添加当前边。
克鲁斯卡尔算法(Kruskal‘s algorithm)是两个经典的最小生成树算法的较为简单理解的一个。这里面充分体现了贪心算法的精髓。大致的流程可以用一个图来表示。这里的图的选择借用了Wikipedia上的那个。非常清晰且直观。
首先第一步,我们有一张图,有若干点和边
第一步我们要做的事情就是将所有的边的长度排序,用排序的结果作为我们选择边的依据。这里再次体现了贪心算法的思想。资源排序,对局部最优的资源进行选择。
排序完成后,我们率先选择了边AD。这样我们的图就变成了
#include <iostream>
#include <algorithm>
using namespace std;
const int mxsz = 1000;
struct Edge{
int st, ed, len;
} edge[mxsz];bool cmp(const Edge &a, const Edge &b) { return a.len < b.len; }
void Kruskal()
{
//输入图
int nodeNum, edgeNum; //节点数量、边的数量
scanf("%d%d", &nodeNum, &edgeNum);
for (int i = 0; i < edgeNum; i++) //输入边
{
int st, ed, len;
scanf("%d%d%d", &st, &ed, &len);
edge[i].st = st, edge[i].ed = ed, edge[i].len = len;
}
//计算最小生成树权值
sort(edge, edge + edgeNum, cmp); //边排序
n = nodeNum; makeSet(); //初始化
int weight = 0;
for (int i = 0; i < edgeNum; i++) //遍历边
if (unionSet(edge[i].st, edge[i].ed) == 1) //合并边的两个节点所在集合
weight += edge[i].len; //如果节点集合不同,加入最小生成树中
printf("最小生成树权值:%d\n", weight);
}版权声明:本文为博主原创文章,未经博主允许不得转载。
标签:
原文地址:http://blog.csdn.net/djd1234567/article/details/48058465