kruskal算法求最小生成樹

kruskal算法是一種使用貪心思路求解無向圖的最小生成樹的算法。

其大體思路爲:將邊按權重排序,然後每次選出權最小且不使圖產生環的邊,作爲樹的邊掛上樹。


具體來講就是這麼兩個步驟:

          1.把邊按權重排序。

          2.依照1的順序遍歷邊:

                    使用一個並查集來判斷加進這條邊後圖中是否有環。

                    如果沒有環,更新並查集,並把此邊加入樹。


並查集判斷環的回顧:

          使用一個數組保存每個點的祖先節點。對於無向圖,可以直接按照點的數字大小作爲代表元的依據,令值小的爲代表元。

         如果兩個點v,w,判斷加入新邊e=<v,w>後是否會產生環的思路是:如果v,w加邊前的代表元相同,那麼就說明v,w間有路,加邊後就會成環。


變量使用: 使用edg[]{v1,v2,w}記錄每個邊的信息,fa[]爲並查集,v,e代表圖的節點,邊數。

       


以hdu1301爲例

#include <bits/stdc++.h>
using namespace std;
const int maxn=200;
struct ed
{
    int v1,v2,w;
    bool operator <(const ed b) const{return w<b.w;}
}edg[maxn];
int v,e,fa[maxn];
int findfa(int pos)
{
    if(fa[pos]==pos)return pos;
    return findfa(fa[pos]);
}
void init()
{
    memset(edg,0,sizeof(edg));
    char c;
    int si,cu;
    e=1;  fa[v]=v;
    for(int i=1;i<v;i++)
    {
        fa[i]=i;
        cin>>c>>si;
        while(si--)
        {
            cin>>c>>cu;
            edg[e].v1=i;
            edg[e].v2=c-'A'+1;
            edg[e].w=cu;
            e++;
        }
    }

    sort(edg+1,edg+e);
}
int kruskal()
{
    int su=0;
    for(int i=1;i<=e;i++)
    {
        int vs=findfa(edg[i].v1),vb=findfa(edg[i].v2);
        if(vs!=vb)
        {
            fa[vb]=vs;
            su+=edg[i].w;
        }
    }
    return su;
}
int main()
{
    while(cin>>v,v!=0)
    {
        init();
        cout<<kruskal()<<endl;
    }
    return 0;
}





 

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