《数据结构与算法分析:C语言描述》复习——第九章“图论”——Prim算法

2014.07.04 22:42

简介:

  给定一个无向带权连通图(三个条件),选出n-1条边将这n个顶点连成一棵树,使得这棵树的权值之和最小。

描述:

  本次使用Prim算法来解决这个问题。Prim算法的思想是两点:BFS与贪婪。

  我们从一个顶点出发,把这个顶点对应的边加入到优先队列中。既然是优先队列,当然是边的权值短的优先。

  每一轮我们从优先队列中取出一条边u->v,u已经被访问过(选出的这条边权值必然是目前最短的),如果v未被访问过,那么标记v,并把从v出发的边加入队列。

  这样从一点出发逐渐散开的搜索形式属于广度优先搜索,而短边优先的策略则属于贪婪。因此Prim算法就是BFS与贪婪算法的结合。

  说实话,直接看代码实现或许更简单。

实现:

  1 // My implementation for Prim's Algorithm, for minimum spanning tree problem.
  2 #include <algorithm>
  3 #include <iostream>
  4 #include <vector>
  5 #include <queue>
  6 using namespace std;
  7 
  8 const int INFINITY = 1000000000;
  9 
 10 struct Edge {
 11     int x;
 12     int y;
 13     int cost;
 14     Edge(int _x = 0, int _y = 0, int _cost = 0): x(_x), y(_y), cost(_cost) {};
 15 };
 16 
 17 struct GreaterFunctor {
 18     bool operator () (const Edge &e1, const Edge &e2) {
 19         return e1.cost > e2.cost;
 20     }
 21 };
 22 
 23 int primsAlgorithm(const vector<vector<int> > &graph)
 24 {
 25     // Prim's Algorithm for weighted undirected graph.
 26     
 27     int n;
 28     n = (int)graph.size();
 29     if (n < 2) {
 30         return 0;
 31     }
 32 
 33     int i;
 34     // Minimal heap, the top is smallest.
 35     priority_queue<Edge, vector<Edge>, GreaterFunctor> pq;
 36     vector<bool> visited;
 37     int visited_count;
 38     int min_cost;
 39     
 40     visited.resize(n, false);
 41     
 42     // Start constructing the tree from 0th vertex.
 43     min_cost = 0;
 44     visited[0] = true;
 45     for (i = 1; i < n; ++i) {
 46         if (graph[0][i] == INFINITY) {
 47             continue;
 48         }
 49         pq.push(Edge(0, i, graph[0][i]));
 50     }
 51     visited_count = n - 1;
 52     
 53     Edge e;
 54     while (!pq.empty()) {
 55         e = pq.top();
 56         pq.pop();
 57         if (visited[e.y]) {
 58             continue;
 59         }
 60         min_cost += e.cost;
 61         visited[e.y] = true;
 62         --visited_count;
 63         if (visited_count == 0) {
 64             break;
 65         }
 66         
 67         for (i = 0; i < n; ++i) {
 68             if (i == e.y || graph[e.y][i] == INFINITY || visited[i]) {
 69                 continue;
 70             }
 71             pq.push(Edge(e.y, i, graph[e.y][i]));
 72         }
 73     }
 74     
 75     while (!pq.empty()) {
 76         pq.pop();
 77     }
 78     
 79     return min_cost;
 80 }
 81 
 82 int main()
 83 {
 84     vector<vector<int> > graph;
 85     int n;
 86     int nk;
 87     int i, j;
 88     int tmp, tmp_dist;
 89     int min_cost;
 90     
 91     while (cin >> n && n > 0) {
 92         graph.resize(n);
 93         for (i = 0; i < n; ++i) {
 94             graph[i].resize(n, INFINITY);
 95         }
 96         
 97         for (i = 0; i < n; ++i) {
 98             cin >> nk;
 99             for (j = 0; j < nk; ++j) {
100                 cin >> tmp >> tmp_dist;
101                 graph[i][tmp] = graph[tmp][i] = tmp_dist;
102             }
103         }
104         
105         min_cost = primsAlgorithm(graph);
106         
107         cout << "The weighted sum of minimum spanning tree is " << min_cost << "." << endl;
108         
109         for (i = 0; i < n; ++i) {
110             graph[i].clear();
111         }
112         graph.clear();
113     }
114     
115     return 0;
116 }
原文地址:https://www.cnblogs.com/zhuli19901106/p/3825215.html