|
Posted on 2009-04-10 19:41 lzmagic 阅读(4550) 评论(1) 编辑 收藏 引用 所属分类: Algorithm
 /**//**
* KRUSKAL 最小生成树算法 (Minimum Spanning Tree)
* 输入:图g; // 有向图或者无向图
* 输出:(1)最小生成树长sum;
* (2)最小生成树mst。
* 结构: 图g用顶点数n和边集edges(优先队列)表示,两点是否连通用并查集实现。
* 算法:Kruskal算法
* 复杂度:O(|E|*log|E|)~O(|E|*log|V|)
*/
#include <iostream>
#include <string>
#include <vector>
#include <deque>
#include <list>
#include <stack>
#include <queue>
#include <set>
#include <map>
#include <bitset>
#include <iterator>
#include <algorithm>
#include <numeric>
#include <functional>
#include <climits>
using namespace std;

struct Edge
  {
int u, v, w; // u、v:两个顶点 w:权
 Edge() { }
 Edge(int u0, int v0, int w0):u(u0), v(v0), w(w0) { }
};

int n; // n : 顶点个数
vector<Edge> edges; // edges : 图g的所有边
int sum; // sum : 最小生成树长
vector<Edge> mst; // mst : 最小生成树(用边集表示)

class DisjSets
  {
vector<int> s;
public:
 DisjSets(int n) : s(n, -1) { };
int find (int x)
 {
if (s[x] < 0) return x;
else return s[x] = find(s[x]); // 压缩路径。
};
void unionSets(int root1, int root2)
 {
if (s[root1] > s[root2]) // 按个数求并(个数用负数表示)。
 {
s[root2] += s[root1];
s[root1] = root2;
}
else
 {
s[root1] += s[root2];
s[root2] = root1;
}
};
};

bool Cmp(const Edge &lhs, const Edge &rhs)
  {
return lhs.w > rhs.w;
}

bool Kruskal()
  {
DisjSets ds(n);
make_heap(edges.begin(), edges.end(), Cmp); // 对边集建堆。
int root1, root2;
Edge e;
while (!edges.empty()) // 遍历所有边,
 {
e = edges.front(); pop_heap(edges.begin(), edges.end(), Cmp); edges.pop_back();// 从未选边集中寻找最小权的边e。
root1 = ds.find(e.u), root2 = ds.find(e.v); // 获取u、v所在的点集,
if (root1 != root2) // 如果u、v不是同一个点集,
 {
sum += e.w; // 调整最小生成树长
mst.push_back(e); // 把边e放入最小生成树mst中,
ds.unionSets(root1, root2); // 合并两点所在的点集。
}
if (mst.size() == n - 1) return true; // 如果选取边个数为n - 1,成功。
}
return false;
}

int main()
  {
n = 7;
edges.clear();
edges.push_back(Edge(0, 1, 2)); edges.push_back(Edge(0, 2, 4)); edges.push_back(Edge(0, 3, 1));
edges.push_back(Edge(1, 3, 3)); edges.push_back(Edge(1, 4, 10));
edges.push_back(Edge(2, 3, 2)); edges.push_back(Edge(2, 5, 5));
edges.push_back(Edge(3, 4, 7)); edges.push_back(Edge(3, 5, 8)); edges.push_back(Edge(3, 6, 4));
edges.push_back(Edge(4, 6, 6));
edges.push_back(Edge(5, 6, 1));
sum = 0;
mst.clear();
if(Kruskal())
 {
cout << sum << endl;
for (vector<Edge>::iterator it = mst.begin(); it != mst.end(); ++it)
cout << it->u << "->" << it->v << endl;
}
else
 {
cout << "Some vertex cann't be reached." << endl;
}
system("pause");
return 0;
}

Feedback
# re: Kruskal算法 回复 更多评论
2010-12-06 22:14 by
这个程序是不是有个bug: 如果节点数量为1,边数量为0 则应该是有生成树的,但是kruskal函数返回结果为false吧 个人意见
|