Prime 算法的簡述


前面在介紹並查集時順便提了Kruskal算法,既然已經說到了最小生成樹問題,就沒有道理不把Prime算法說了。

這里面先補充下Kruskal算法的大概意思,Kruskal算法通過把所有的邊從小到大排列后,不斷取權值最小的邊加入最小生成樹(起初可能是離散的多個樹,最終連成一個整體),並通過並查集來舍棄形成回路的邊。

Prime算法有所不同,Prime算法先將一個起點加入最小生成樹,之后不斷尋找與最小生成樹相連的邊權最小的邊能通向的點,並將其加入最小生成樹,是一種更符合人的主觀直覺的最小生成樹算法。

需要注意的是,Kruskal和Prime都僅適用於無向圖。

#include <algorithm>
const int MAX_V = 100;
const int INF = 1000000;
int cost[MAX_V][MAX_V];//
int V;
bool path[MAX_V][MAX_V];//記錄結果
int res;
bool used[MAX_V];//表示是否訪問過
int mincost[MAX_V];//表示到此點消耗值

void Prime()
{
    res = 0;//統計最小消耗
    for (int i = 0;i < V;++i)//初始化
    {
        used[i] = false;
        mincost[i] = INF;
        for (int j = 0;j < V;++j)
        {
            path[i][j] = false;
        }
    }
    mincost[0] = 0;//從0點開始
    int prev = 0;//記錄路徑
    while (true)
    {
        int visited = -1;
        for (int i = 0;i < V;++i)
        {
            if (!used[i] && (visited == -1 || mincost[i] < mincost[visited])) visited = i;//貪婪尋找最短邊
        }
        if (visited == -1) break;
        used[visited] = true;
        if (visited)
        {
            path[prev][visited] = true;
            prev = visited;
        }
        res += mincost[visited];
        for (int i = 0;i < V;++i)
        {
            mincost[i] = std::min(mincost[i], cost[visited][i]);
        }
    }
}

 

下面給出一組Kruskal和Prime的測試數據及結果:

測試代碼:

void mstTest()
{
    cin >> V;
    for (int i = 0;i < V;++i)
        for (int j = 0;j < V;++j)
        {
            cin >> cost[i][j];
        }            
    for (int i = 0;i < V;++i) d[i] = INF;
    cout << "Kruskal:" << endl;
    Kruskal();
    for (int i = 0;i < V;++i)
    {
        for (int j = 0;j < V;++j)
        {
            if (path[i][j]) cout << i << " " << j << endl;
        }
    }
    cout << res << endl;
    cout << endl;
    cout << "Prime" << endl;
    Prime();
    for (int i = 0;i < V;++i)
    {
        for (int j = 0;j < V;++j)
        {
            if (path[i][j]) cout << i << " " << j << endl;
        }
    }
    cout << res << endl;
}

 

測試結果:

9
1000000 1 5 7 4 1000000 1000000 1000000 1000000
1 1000000 1000000 1000000 1000000 3 10 1000000 1000000
5 1000000 1000000 1000000 1000000 2 1000000 2 1000000
7 1000000 1000000 1000000 1000000 1000000 1 1000000 1000000
4 1000000 1000000 1000000 1000000 1000000 1000000 3 1000000
1000000 3 2 1000000 1000000 1000000 1000000 1000000 2
1000000 10 1000000 1 1000000 1000000 1000000 1000000 9
1000000 1000000 2 1000000 3 1000000 1000000 1000000 5
1000000 1000000 1000000 1000000 1000000 2 9 5 1000000
Kruskal:
0 1
0 3
1 5
2 5
2 7
3 6
4 7
5 8
21

Prime
0 1
1 5
2 7
3 6
4 3
5 2
7 8
8 4
21
請按任意鍵繼續. . .

可以看到,兩種算法生成了擁有相同最小消耗的兩顆完全不同的最小生成樹。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM