最小生成樹MST

邊的權值之和最小的生成樹Minimum-Spanning-Tree
假設G=(V, E)是一個帶權連通無向圖,U是頂點集V的一個非空子集。若(u, v)是一條具有最小權值的邊,其中u∈U,v∈V-U,則必存在一棵包含邊(u, v)的最小生成樹。
任意一個生成樹T,添加一條邊e則會產(chǎn)生回路,刪除該回路中的任一條邊,則又恢復為生成樹,若e小于刪除的那條邊,則得到一個更小的生成樹。
在建立的時候,所添加的邊都為避免生成回路的可添加的邊中最小的,則最后生成的生成樹是不可改進的。任意邊換進去得到的回路中,換進去的那條邊一定是最大的。
采用貪心算法

GENERIC_MST(G)
{
    T=NULL;
    while T未形成一棵生成樹;
        do 找到一條最小代價邊(u, v)并且加入T后不會產(chǎn)生回路;
            T=TU(u, v);
}

Prim

初始化:向空樹T=(VT, ET)中添加圖G=(V, E)的任一頂點u0,使VT={u0},ET=空集
循環(huán)(重復下列操作至VT=V):從G中選擇滿足{(u, v)|u∈VT,v∈V-VT}且具有最小權值的邊(u, v),把v加入VT,這條邊加入ET
時間復雜度O(|V|^2)不依賴于|E|,因此適用于求解邊稠密的圖的最小生成樹。

struct{
    VertexType adjvex; //與哪個VT中的點相連
    VRType lowcost;  //權值
}closeedge[MAX_SIZE];
//數(shù)組下標與圖的點數(shù)組下標一致

void MiniSpanTree(MGraph G, VertexType u)
{
    k=LocateVex(G, u);
    for(j=0;j<G.vexnum;++j)
        if(j!=k)
            closeedge[j]={u, G.arcs[k][j];
    closeedge[k].lowcost=0;
    for(i=0;i<G.vexnum;++i)
    {
        k=minimum(closeedge);    //下一個要加入生成樹的點
        printf(closeedge[k].adjvex, G.vexs[k]);    //輸出生成樹上一條邊
        closeedge[k].lowcost=0;    //將k加入VT
        for(j=0;j<G.vexnum;++j)    //修改其它頂點的最小邊
            if(G.arcs[k][j]<closeedge[j].lowcost)
                closeedge[j]={G.vexs[k], G.arcs[k][j]}
}

Kruskal

Prim是選頂點,Kruskal是選邊
初始化:VT=V,ET=空集,每個頂點構成一棵獨立的樹
循環(huán)(重復下列操作至T是一棵樹):按G的邊的權值遞增順序依次從E-ET中選擇一條邊,若這條邊加入T后不構成回路,則加入ET,知道ET中有n-1條邊。
用類似于并查集的算法,通常采用堆來存放邊的集合,每次選擇最小權值的邊只需O(log|E|)
時間復雜度O(|E|log|E|),適用于邊稀疏而頂點較多的圖。

Typedef struct{
    int vi, vj, w;
}edgeset[MAX_SIZE_E];

int set[MAX_SIZE_V];

int FindSet(int set[], int v)
{
    i=v;
    while(set[i]>0) i=set[i];
    return i;
}

void krusal(edgeset get, int n, int e)
{
    //get為權按從小到大到順序排序的邊集數(shù)組
    for(i=0;i<=n;++i)  set[i]=0;
    i=1; //get中的下標
    j=1; //生成樹中的邊數(shù)
    while(j<n)//一共要獲得n-1條邊
    {
        v=FindSet(set, get[i].vi);
        w=FindSet(set, get[i].vj);
        if(v!=w){
            //vi,vj不在同一集合,不會構成回路
            cout<<get[i].vi<<","<<get[i].vj<<endl;
            set[v]=w;
            ++j;
        }
        ++i;
    }
}
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內(nèi)容