1. 程式人生 > >Prim演算法求最小生成樹的c++程式碼實現

Prim演算法求最小生成樹的c++程式碼實現

Prim演算法是求解最小生成樹的常用方法,它的思想非常簡單,講所有的點集合V分為 已經放入最小生成樹集合的S和未放入的V-S,每次在V-S中選擇一個距離S最近的點放入到S中,直到所有的點都放入S。就是很簡單的貪心策略,不過可以證明是全域性最優,prim演算法對於稠密圖效果比較好,具體步驟可以看點選開啟連結,講解的很清楚。

對於上面的圖,顯然最小生成樹的結果應該是{1,3,6,2,4,5}或者{1,3,6,4,2,5}

#include <iostream>
#include<vector>

using namespace std;

#define MAX_INT 999999
pair<int,int> GetShortestEdge(const vector<vector<int> >& Graph, const vector<bool>& isIncluded )//求當前在MST之外距離MST最近的點的id
{
    int minID = -1;
    int minDist = MAX_INT;
    pair<int,int> minEdge;
    for(int i = 0; i < Graph.size(); i++)//i為MST內的點
    {
        if(!isIncluded[i]) continue;//如果不在MST裡面,則跳過
        for(int j = 0; j < Graph.size(); j++) //j為MST外的點
            if(!isIncluded[j] && Graph[i][j] < minDist){ //找到不在MST內但是距離MST最近的點
                minID = j;
                minDist = Graph[i][j];
                minEdge = make_pair(i,j);
            }
    }
    return minEdge;

}

vector<pair<int,int> > Prim(const vector<vector<int> >& Graph, vector<bool>& isIncluded){
    vector<pair<int,int> > MST;
    isIncluded[0] = true;
    //MST.push_back();
    for(int i = 1; i < Graph.size(); i++){
        pair<int,int> minEdge = GetShortestEdge(Graph, isIncluded); //找到這次要放入的邊i,j
        MST.push_back(minEdge); //放入
        isIncluded[minEdge.second] = true; //將j標記為已經放入
    }
    return MST;
}

void addEdge( const int& startP, const int& endP, const int& weight ,vector<vector<int> >& Graph)
{
    Graph[startP][endP] = weight;
    Graph[endP][startP] = weight;
}

int main()
{
    int vertex_num = 6;
    vector<vector<int> > Graph(vertex_num, vector<int>(vertex_num, MAX_INT));
    addEdge(0,1,6 ,Graph);
    addEdge(0,2,1 ,Graph);
    addEdge(0,3,5 ,Graph);
    addEdge(1,2,5 ,Graph);
    addEdge(1,4,3 ,Graph);
    addEdge(2,3,5 ,Graph);
    addEdge(2,4,6 ,Graph);
    addEdge(2,5,4,Graph);
    addEdge(3,5,2,Graph);
    addEdge(4,5,6,Graph);
    vector<bool> isIncluded(vertex_num, false);
    vector<pair<int,int> >  MST = Prim(Graph, isIncluded);
    for(int i = 0; i < MST.size(); i++) //按照放入MST的順序依次輸出
        cout << MST[i].first+1 << "->" << MST[i].second+1 << endl;

    return 0;
}

結果如下