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 }

浙公网安备 33010602011771号