Prim's Minimal Spanning Tree_Prim(最小生成树的Prim算法)

题目:

    最小生成树是什么?在图的一堆点(假设有V个)中,有些两点之间有边,有些两点之间没有边。对于两点之间的边,权重有大有小,题目目标是找到一些边,使得图是联通的并且这些边的和最小。

算法:

    贪心。

代码:

(搬运自GeeksForGeeks)

#ifndef MST_Prim_Solution_h
#define MST_Prim_Solution_h
#include <iostream>
#include <string>
#include <vector>
#include <map>
#include <set>
#include <unordered_map>
#include <unordered_set>
#include <queue>
#include <stack>
#include <cmath>
#include <algorithm>
using namespace std;
#define V 5

class Solution{
public:
    //辅助函数,找到当前即将新加入点,这个点之前没被使用过,并且和某个已经使用的点构成了一条边,这条边是当前最小的边。
    int minKey(int key[], bool mstSet[]) //或者int minKey(int* key, bool* mstSet)
    {
        int min = INT_MAX, min_index;
        for (int v = 0;v<V;v++)
            if (mstSet[v] == false && key[v] < min){
                min = key[v];
                min_index = v;
            }
        return min_index;
    }
    
    //辅助函数
    void printMST(int parent[], int n, int graph[V][V]) //或者void printMST(int* parent, int n, int (*graph)[V])

    {
        printf("Edge   Weight\n");
        for (int i = 1; i < V; i++)
            printf("%d - %d    %d \n", parent[i], i, graph[i][parent[i]]);
    }
    
    void primMST(int graph[V][V])
    {
        int parent[V]; // 记载历史路径
        int key[V];   // 记载当前未使用的点v和当前已经使用的点u的所有边中的最短边。
        bool mstSet[V];  // 标记点是否已经被用来生成树了
        
        for (int i = 0; i < V; i++){
            key[i] = INT_MAX;
            mstSet[i] = false;
        }
        
        key[0] = 0;     // Make key 0 so that this vertex is picked as first vertex
        parent[0] = -1;
        
        for (int count = 0; count < V-1; count++)
        {

            int u = minKey(key, mstSet);
            std::cout<<"u="<<u<<std::endl;
            mstSet[u] = true;
            for (int v = 0; v < V; v++)
                if (graph[u][v] && mstSet[v] == false && graph[u][v] <  key[v]){ //根据原题意,无法连接的点u和v的距离设定0,并且点和自己的距离为0.
                    parent[v]  = u;
                    key[v] = graph[u][v];
                }
        }
        printMST(parent, V, graph);
    }
};
#endif

main函数如下:

#include <iostream>
#include "Solution.h"

int main(int argc, const char * argv[])
{
        /* Let us create the following graph
         2    3
         (0)--(1)--(2)
         |   / \   |
         6| 8/   \5 |7
         | /     \ |
         (3)-------(4)
         9          */
    
        int graph[V][V] = {
            {0, 2, 0, 6, 0},
            {2, 0, 3, 8, 5},
            {0, 3, 0, 0, 7},
            {6, 8, 0, 0, 9},
            {0, 5, 7, 9, 0},
        };
    
        Solution s1;
        s1.primMST(graph);
        std::cout << "graph MST Prim created now!\n";
        return 0;
}
运行结果如下:

Edge   Weight
0 - 1    2 
1 - 2    3 
0 - 3    6 
1 - 4    5 
graph MST Prim created now!

参考资料

http://www.geeksforgeeks.org/greedy-algorithms-set-5-prims-minimum-spanning-tree-mst-2/

你可能感兴趣的:(图,贪心算法)