首页 > 代码库 > 《数据结构与算法分析:C语言描述》复习——第九章“图论”——Kruskal算法
《数据结构与算法分析:C语言描述》复习——第九章“图论”——Kruskal算法
2014.07.04 23:03
简介:
给定一个无向带权连通图(三个条件),选出n-1条边将这n个顶点连成一棵树,使得这棵树的权值之和最小。
描述:
本次使用Kruskal算法来解决这个问题。
如果有n个顶点的话,我们需要n-1条边来拼成一棵树。
Kruskal算法的基本思路,是每次拼上一条边,看看是否会造成一个环,如果会形成环则放弃这条边。
怎么保证拼成的那棵树权值最小呢?把所有边按权值由小到大排序。从小到大一个个试就可以了。
怎么确定加入一条边后是否会形成环呢?用并查集。对于一条无向图的边u-v,如果并查集中u和v对应的根节点相同,代表u、v已经连通了,这时再加入u-v就会形成一个环。
Kruskal算法可以说是学完并查集之后的第一个应用了。
由于需要对所有边进行排序,所以Kruskal算法的效率对于密集图(和恐惧症无关)肯定不那么好。
实现:
1 // My implementation for Prim‘s Algorithm, for minimum spanning tree problem. 2 #include <algorithm> 3 #include <iostream> 4 #include <vector> 5 using namespace std; 6 7 const int INFINITY = 1000000000; 8 9 struct Edge { 10 int x; 11 int y; 12 int cost; 13 Edge(int _x = 0, int _y = 0, int _cost = 0): x(_x), y(_y), cost(_cost) {}; 14 }; 15 16 bool comparator(const Edge &e1, const Edge &e2) { 17 return e1.cost < e2.cost; 18 } 19 20 int findRoot(vector<int> &dj, int x) 21 { 22 int r, k; 23 24 r = x; 25 while (r != dj[r]) { 26 r = dj[r]; 27 } 28 29 // Path compression speeds up the disjoint set. 30 k = x; 31 while (x != r) { 32 x = dj[x]; 33 dj[k] = r; 34 k = x; 35 } 36 37 return r; 38 } 39 40 int kruskalsAlgorithm(const vector<vector<int> > &graph) 41 { 42 // Kruskal‘s Algorithm for weighted undirected graph. 43 int n; 44 n = (int)graph.size(); 45 if (n < 2) { 46 return 0; 47 } 48 49 // Disjoint set 50 vector<int> dj; 51 vector<Edge> edges; 52 int rx, ry; 53 int i, j; 54 55 for (i = 0; i < n; ++i) { 56 for (j = i + 1; j < n; ++j) { 57 if (graph[i][j] == INFINITY) { 58 continue; 59 } 60 edges.push_back(Edge(i, j, graph[i][j])); 61 } 62 } 63 sort(edges.begin(), edges.end(), comparator); 64 65 dj.resize(n); 66 for (i = 0; i < n; ++i) { 67 dj[i] = i; 68 } 69 70 int edge_count = n - 1; 71 int min_cost = 0; 72 int ec = (int)edges.size(); 73 for (i = 0; i < ec; ++i) { 74 rx = findRoot(dj, edges[i].x); 75 ry = findRoot(dj, edges[i].y); 76 if (rx == ry) { 77 continue; 78 } 79 dj[rx] = ry; 80 findRoot(dj, edges[i].x); 81 82 min_cost += edges[i].cost; 83 --edge_count; 84 if (edge_count == 0) { 85 break; 86 } 87 } 88 edges.clear(); 89 90 return min_cost; 91 } 92 93 int main() 94 { 95 vector<vector<int> > graph; 96 int n; 97 int nk; 98 int i, j; 99 int tmp, tmp_dist;100 int min_cost;101 102 while (cin >> n && n > 0) {103 graph.resize(n);104 for (i = 0; i < n; ++i) {105 graph[i].resize(n, INFINITY);106 }107 108 for (i = 0; i < n; ++i) {109 cin >> nk;110 for (j = 0; j < nk; ++j) {111 cin >> tmp >> tmp_dist;112 graph[i][tmp] = graph[tmp][i] = tmp_dist;113 }114 }115 116 min_cost = kruskalsAlgorithm(graph);117 118 cout << "The weighted sum of minimum spanning tree is " << min_cost << "." << endl;119 120 for (i = 0; i < n; ++i) {121 graph[i].clear();122 }123 graph.clear();124 }125 126 return 0;127 }
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。