Kruskal算法

问题描述:求无向连通图G<V, E>最小生成树(MST)。(不知道什么是MST的见Prim算法中的算法依据一栏)

算法步骤:

本质是贪心。

①   将G中的n个顶点看成是n个独立的连通分量,可记为T<V,X>

②   每次找当前剩余的权值最小的边,若分属不同的连通分量,则将其加入T

③   重复②,直到所有点连通

算法实现:

①   取权值最小的边,可使用最小堆或快排。

②   判断是否属于同一连通分量,可基于树的父指针表示法中的并查集算法。并查集可以使用重量权衡合并规则和路径压缩进行优化。

算法补充:

并查集算法:把n个节点分到多个集合,快速查找属于哪个集合,快速合并两个集合的算法。

方法是使用森林,同一个集合的点在森林的同一棵树里,拥有同一个根节点。节点采用父指针表示法,即每个节点有指向父结点的指针,根节点无父节点。合并两个集合相当于合并两棵树,只要把一棵树的根节点改为另一棵的根节点即可。查集只要不断向上直到根节点,如果是根节点相同代表在同一个集合内。
并查集优化:

重量权衡合并规则:结点较少树的根结点指向结点较多树的根结点。

路径压缩:查找一个结点X的根结点时可以采用路径压缩。设根结点为R,则路径压缩把由X到R的路径上每个结点的父指针均设置为直接指向R。

算法复杂度:O(eloge) e为边数

 

例:POJ 1251 Jungle Roads

 

View Code
 1 View Code 
 2 
 3 #include <iostream>
 4 #include <set>
 5 using namespace std;
 6 
 7 int n;
 8 class Edge
 9 {
10 public:
11     int x, y, cost;
12     Edge(int x_, int y_, int cost_): x(x_), y(y_), cost(cost_){};
13     bool operator< (const Edge& e) const{    return cost < e.cost;}
14 };
15 multiset<Edge> edge;//sorted
16 class ParTree//Parent Tree;
17 {
18 private:
19     int a[26];
20     int size[26];
21 public:
22     ParTree()
23     {
24         for (int i = 0; i < 26; i++)
25         {
26             a[i] = i;
27             size[i] = 1;
28         }
29     }
30     int Find(int i)//找到c所属根节点
31     {
32         if (i == a[i])
33             return i;
34         a[i] = Find(a[i]);//路径压缩
35         return a[i];
36     }
37     void Union(int i, int j)
38     {
39         int p = Find(i);
40         int q = Find(j);
41         if (size[p] < size[q])//重量权衡,轻者并入重者
42         {
43             a[p] = q;
44             size[q] += size[p];
45         }
46         else
47         {
48             a[q] = p;
49             size[p] += size[q];
50         }
51     }
52 };
53 
54 int Kruskal()
55 {
56     ParTree* p = new ParTree;
57     int totalCost = 0;
58     int MstEdgeNum = 0;
59 
60     for (multiset<Edge>::iterator i = edge.begin(); i != edge.end(); i++)
61     {
62         if (p->Find(i->x) == p->Find(i->y))
63             continue;
64         p->Union(i->x, i->y);
65         totalCost += i->cost;
66         MstEdgeNum++;
67         if (MstEdgeNum == n-1)//MST has n-1 edges
68             return totalCost;
69     }
70     return -1;
71 }
72 int main(void)
73 {
74     char c1,c2;
75     int t, len;
76     while (cin >> n, n)
77     {
78         edge.clear();
79         for (int i = 0; i < n-1; i++)
80         {
81             cin >> c1;
82             cin >> t;
83             for (int j = 0; j < t; j++)
84             {
85                 cin >> c2;
86                 cin >> len;
87                 edge.insert(Edge(int(c1-'A'), int(c2-'A'), len));
88             }
89         }
90         cout << Kruskal() << endl;
91     }
92     //system("pause");
93     return 0;
94 }

 

 

 

posted on 2012-12-12 12:42  澄哥  阅读(1006)  评论(0)    收藏  举报

导航