Prim算法

(一)Prim算法的功能:

    Prim算法实现的是找出一个有权重连通图中的最小生成树,即:具有最小权重且连接到所有结点的树。(强调的是树,树是没有回路的)。

(二)算法的基本思想: 

    首先以一个结点作为最小生成树的初始结点,然后以迭代的方式找出与最小生成树中各结点权重最小边,并加入到最小生成树中。加入之后如果产生回路则跳过这条边,选择下一个结点。当所有结点都加入到最小生成树中之后,就找出了连通图中的最小生成树了。

(三)算法的基本步骤:

    a.假定图的顶点集合为V,边集合为E.
    b.初始化点集合U={u}.//u为V中的任意选定的一点
    c.从u的邻接结点中选取一点v使这两点之间的权重最小,(可能存在多条边可选,任选其中一条即可)且不构成回路,然后将v加入集合U中.
    d.从结点v出发,重复c步骤,直到V={}.

(四)算法有以下几个函数构成

1.初始化图

for (i = 1; i <= n; i++)
{
   for (j = 1; j <= n; j++)
   {
      map[i][j] = MAXCOST;
   }
}

2.构造图

1 for (k = 1; k <= m; k++)
2 {
3       cin >> i >> j >> cost;
4       map[i][j] = cost;
5       map[j][i] = cost;
6 }

(五)优先队列表示Prim算法

 1 struct node {  
 2     int v, len;  
 3     node(int v = 0, int len = 0) :v(v), len(len) {}  
 4     bool operator < (const node &a)const {  // 加入队列的元素自动按距离从小到大排序  
 5         return len> a.len;  
 6     }  
 7 };
 8 
 9 vector<node> G[maxn];
10 int vis[maxn];
11 int dis[maxn];
12 
13 void init() {  
14     for (int i = 0; i<maxn; i++) {  
15         G[i].clear();  
16         dis[i] = INF;  
17         vis[i] = false;  
18     }  
19 }  
20 int Prim(int s) {  
21     priority_queue<node>Q; // 定义优先队列  
22     int ans = 0;  
23     Q.push(node(s,0));  // 起点加入队列  
24     while (!Q.empty()) {   
25         node now = Q.top(); Q.pop();  // 取出距离最小的点  
26         int v = now.v;  
27         if (vis[v]) continue;  // 同一个节点,可能会推入2次或2次以上队列,这样第一个被标记后,剩下的需要直接跳过。  
28         vis[v] = true;  // 标记一下  
29         ans += now.len;  
30         for (int i = 0; i<G[v].size(); i++) {  // 开始更新  
31             int v2 = G[v][i].v;  
32             int len = G[v][i].len;  
33             if (!vis[v2] && dis[v2] > len) {   
34                 dis[v2] = len;  
35                 Q.push(node(v2, dis[v2]));  // 更新的点加入队列并排序  
36             }  
37         }  
38     }  
39     return ans; 
40 }  

(六)C++完整代码

 1 #include<iostream>
 2 using  namespace std;
 3 
 4 #define MAX 100
 5 #define MAXCOST 0x7fffffff
 6 
 7 int map[MAX][MAX];
 8 //二维数组适合复杂树
 9 int prim(int map[][MAX], int n)
10 {
11     int dis[MAX];
12     int i, j, min, minid, sum = 0;
13     for (i = 2; i <= n; i++)
14     {
15         dis[i] = map[1][i];//dis[i]表示从根节点到i结点的最小距离
16     }
17     for (i = 2; i <= n; i++)
18     {
19         min = MAXCOST;
20         minid = 0;
21         for (j = 2; j <= n; j++)
22         {
23             if (dis[j] < min && dis[j] != 0)
24             {
25                 min = dis[j];
26                 minid = j;
27             }
28         }
29         sum += min;
30         dis[minid] = 0;
31         for (j = 2; j <= n; j++)
32         {
33             if (map[minid][j] < dis[j])
34             {
35                 dis[j] = map[minid][j];
36             }
37         }
38     }
39     return sum;
40 }
41 
42 int main()
43 {
44     int i, j, k, m, n;
45     int cost;
46     cin >> n >> m;//n顶点的个数,m边的个数
47     //初始化图G
48     for (i = 1; i <= n; i++)
49     {
50         for (j = 1; j <= n; j++)
51         {
52             map[i][j] = MAXCOST;
53         }
54     }
55     //构建图G
56     for (k = 1; k <= m; k++)
57     {
58         cin >> i >> j >> cost;
59         map[i][j] = cost;
60         map[j][i] = cost;
61     }
62     //求解最小生成树
63     cost = prim(map, n);
64     //输出最小权值和
65     cout << "最小权值和=" << cost << endl;
66     return 0;
67 }


原文地址:https://www.cnblogs.com/--lr/p/6718103.html