Kruskal算法
Kruskal算法将无向图中的每一个点看做一个单独的集合(即一个连通图)。事先需要对所有权值进行排序,之后按由小到大的次序取权值。从第一个顶点开始找最小的边,并将第二个顶点设置为与第一个点连通,以此循环。
其中该算法需要用到不相交集(并查集)来实现Kruskal算法。
其中不相交集有三个主要的函数
Make-set(x) 建立一个新的集合,其唯一成员就是x。
UNION( x , y ) 将包含x和y的动态集合合并为一个新的集合。假定在这个操作之前两个集合是不相交的。在经过此操作之后,所得集合的代表可以是Sx 和 Sy的并集中的任何 元素。
FIND-SET ( x ) 返回一个指针,指向包含 x 的集合的代表。
Kruskal算法的时间复杂度为 O(ElgE) 。
代码实现
#include <iostream>
#include <algorithm>
using namespace std;
const int maxn = 10000;
struct edge
{
int a ,b;
int weight;
bool operator <(const edge& cur) const
{
return weight < cur.weight;
}
};
int parent[maxn];
edge e[maxn];
edge mst[maxn]; //生成树的数组
void makeset( int n)
{
for( int i = 0 ; i < n; i++)
parent[i] = i;
}
int getparent(int i)
{
if(parent[i] != i)
{
parent[i] = getparent(parent[i]);
}
return parent[i];
}
//假定可以合并,可以合并则合并返回真,不能合并则返回假
bool unionset(int father , int son)
{
int f = getparent(father);
int s = getparent(son);
if( f == s)
return false;
parent[s] = f;
return true;
}
//节点0打印为节点A
//仅提供主函数在节点数目很小的情况下使用,方便检查边
char trans( int i)
{
return i+'A';
}
int main()
{
int n , m ; //顶点个数 ,边数
int k = 0;
int weight_sum = 0;
cin >> n >> m;
for( int i = 0; i < 2*m; i++) //假定输出无向图的边,其边数为2*m
{
cin >> e[i].a >> e[i].b >> e[i].weight;
}
makeset(n);
sort(e,e+2*m); //排序
for( int i = 0 ; i != 2*m; i++)
{
if(unionset(e[i].a , e[i].b))
{
mst[k++] = e[i];
weight_sum += e[i].weight;
}
}
//输出mst
for( int i = 0 ; i != k ;i++)
{
cout << trans(mst[i].a) << "->" << trans(mst[i].b) << " " << "weight= "<< mst[i].weight <<endl;
}
cout << "weight_sum= " << weight_sum << endl;
return 0 ;
}
引用 http://blog.csdn.net/architect19/article/details/8924538