最小生成樹之prim算法與kruskal算法

給定一個帶權值的無向圖,那麼權值之和最小的生成樹,我們就稱之爲最小生成樹(MST)。

(1)Prim算法是圖論中的一種算法,可在加權連通圖裏搜索最小生成樹。由此算法搜索到的邊子集所構成的樹中,不但包括了連通圖裏的所有頂點(Vertex (graph theory)),且其所有邊的權值之和亦爲最小。

算法代碼及其註釋如下(首先請參考代碼下面的鏈接理解算法流程):

#include<iostream>  
#include<fstream>  
using  namespace std;  

#define MAX 100                 //暫時設圖中一共有100個點
#define MAXCOST 0x7fffffff     //long int 裏的最大值

int graph[MAX][MAX];         //圖的鄰接矩陣

int prim(int graph[][MAX], int n)   //最小生成樹函數 
{  
    int lowcost[MAX];        //lowcost[i]的值爲i點的權值
    int mst[MAX];            //mst[i]的值爲與i點(終點)相連的那條邊的另一個點(始點)
    int i, j, min, minid, sum = 0;  //min爲當前次數預計連入最小生成樹的最小權值(最小邊的長度),minid爲當前次數預計連入最小生成樹的點,sum爲當前次數最小生成樹上權值之和
    for (i = 2; i <= n; i++)  
    {  
        lowcost[i] = graph[1][i];    //表示i點到1點(當前最小生成樹)的權值(邊的長度)
        mst[i] = 1;   //當前次數下與i點連接的邊的另一個點都是1點
    }  
    mst[1] = 0;  //表示11點已經在最小生成樹內
    for (i = 2; i <= n; i++)  
    {  
        min = MAXCOST;  
        minid = 0;      //每一次循環前恢復初始設定
        for (j = 2; j <= n; j++)  
        {  
            if (lowcost[j] < min && lowcost[j] != 0) //尋找與當前最小生成樹相連的最小權值(最短的邊長)與相連的點(j點),同時確保j點不在當前最小生成樹內 
            {  
                min = lowcost[j];  
                minid = j;       //賦值
            }  
        }  
        cout << "V" << mst[minid] << "-V" << minid << "=" << min << endl;   //打印當前次數下由mst[minid]點接minid點,它們之間的邊長(此時已確定爲最短)min
        sum += min;  
        lowcost[minid] = 0;  //將此時的mind點放入最小生成樹內
        for (j = 2; j <= n; j++)  
        {  
            if (graph[minid][j] < lowcost[j])  
            {  
                lowcost[j] = graph[minid][j];  //重新確定j點與當前最小生成樹間的最小權值(最短的邊長)
                mst[j] = minid;  //與j點相連的邊的另一個點爲minid點
            }  
        }  
    }  
    return sum;  
}  

int main()  
{  
    int i, j, k, m, n;  
    int x, y, cost;  
    ifstream in("input.txt");  
    in >> m >> n;//m=頂點的個數,n=邊的個數  
    //初始化圖G  
    for (i = 1; i <= m; i++)  
    {  
        for (j = 1; j <= m; j++)  
        {  
            graph[i][j] = MAXCOST;
            graph[j][i] = MAXCOST;     //假設圖中的每兩個頂點間的距離爲無窮大
        }  
    }  
    //構建圖G  
    for (k = 1; k <= n; k++)  
    {  
        in >> i >> j >> cost;   //輸入兩個點及這兩點間的距離(權值)
        graph[i][j] = cost;  
        graph[j][i] = cost;  
    }  
    //調用最小生成樹函數  
    cost = prim(graph, m);  
    //輸出最小權值和  
    cout << "最小權值和=" << cost << endl;  
    system("pause");  
    return 0;  
}  

參考鏈接:
http://blog.csdn.net/yeruby/article/details/38615045

kruskal算法:
先構造一個只含 n 個頂點、而邊集爲空的子圖,把子圖中各個頂點看成各棵樹上的根結點,之後,從網的邊集 E 中選取一條權值最小的邊,若該條邊的兩個頂點分屬不同的樹,則將其加入子圖,即把兩棵樹合成一棵樹,反之,若該條邊的兩個頂點已落在同一棵樹上,則不可取,而應該取下一條權值最小的邊再試之。依次類推,直到森林中只有一棵樹,也即子圖中含有 n-1 條邊爲止。

參考鏈接:
http://blog.csdn.net/luomingjun12315/article/details/47700237
(註釋較少看着吃力)(優推)

http://www.cnblogs.com/biyeymyhjob/archive/2012/07/30/2615542.html
(從鄰接矩陣的角度來看兩種算法)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章