最小產生樹之prime演算法實現

來源:互聯網
上載者:User

prime演算法的精髓在於:

每次選取一條邊。

該邊滿足:1、一端已選,一端未選;2、該邊權值最小。

直到選取n-1條邊或選取n個頂點演算法結束,求出MST或者判斷出不存在MST。

 

代碼設計:

1、利用兩個集合存放已選頂點和未選頂點

(choosed[]存放已選頂點,unchoosed[]存放未選頂點)

2、每次選取的邊都是一端在choosed[]中,另一端在unchoosed[]中的權值最小的邊

3、利用STL中vector可以方便的實現圖的臨界表格儲存體

4、記錄組成MST的每條邊很方便,只要在選取到一條滿足條件的邊時記錄下起點、終點、權值即可

 

代碼:

#include<iostream>#include<cstring>#include<vector>using namespace std;const int maxn=101;    //頂點數 const int INF=0x7fffffff;struct edge  //邊 {    int to;    //到達的點     int cost;  //邊的花費     bool flag; //是否入選 };int choosed[maxn];      //已選頂點 int unchoosed[maxn];    //未選頂點 int nodeNum,edgeNum,MST;  //頂點數、邊數、最小產生樹 bool choose[maxn];     //頂點是否已選 vector<edge> myV[maxn];  //圖的鄰接表 /*   //這是無向圖有重複邊的建圖,取重複邊中最小的邊儲存 bool exist(int from,int to,int cost){    bool existFlag=false,smallFlag=false;        for(int i=0;i<myV[from].size();i++)    {        if(myV[from][i].to==to)        {            existFlag=true;                        if(myV[from][i].cost>cost)            {                smallFlag=true;                myV[from][i].cost=cost;                break;            }        }    }        if(smallFlag)    {        for(int j=0;j<myV[to].size();j++)        {            if(myV[to][j].to==from)            {                myV[to][j].cost=cost;                break;            }        }    }        if(existFlag) return true;    return false;}             void storeMap()   //鄰接表存圖 {    for(int j=0;j<maxn;j++)  //清空     {        myV[j].clear();    }        memset(choose,false,sizeof(choose));  //標誌圖的各個點是否被選,不能重複         int from,to,cost,num=0;  //從from到to花費cost的邊         for(int i=0;i<edgeNum;i++)    {        scanf("%d%d%d",&from,&to,&cost);                //把圖上的所有點不重複的放到unchoosed[]表中        if(!choose[from])        {            unchoosed[num++]=from;            choose[from]=true;        }        if(!choose[to])        {            unchoosed[num++]=to;            choose[to]=true;        }                              if(!exist(from,to,cost))  //圖中存在重複邊的處理         {            edge tmp;                        tmp.flag=false;            tmp.cost=cost;                        //無向圖             tmp.to=to;            myV[from].push_back(tmp);                        tmp.to=from;            myV[to].push_back(tmp);        }    }}*///無向圖,無重複邊的建圖 void storeMap()   //鄰接表存圖 {    for(int j=0;j<maxn;j++)  //清空     {        myV[j].clear();    }        memset(choose,false,sizeof(choose));  //標誌圖的各個點是否被選,不能重複         int from,to,cost,num=0;  //從from到to花費cost的邊         for(int i=0;i<edgeNum;i++)    {        scanf("%d%d%d",&from,&to,&cost);                //把圖上的所有點不重複的放到unchoosed[]表中        if(!choose[from])        {            unchoosed[num++]=from;            choose[from]=true;        }        if(!choose[to])        {            unchoosed[num++]=to;            choose[to]=true;        }                              edge tmp;          tmp.flag=false;        tmp.cost=cost;                    //無向圖         tmp.to=to;        myV[from].push_back(tmp);                    tmp.to=from;        myV[to].push_back(tmp);    }} void prime()  //prime演算法 {    //初始化一些資訊     MST=0;    memset(choose,false,sizeof(choose));    choosed[0]=unchoosed[0];    choose[unchoosed[0]]=true;        int choosedNum=1,from,to,cost,index;        while(choosedNum<nodeNum)    {        cost=INF;                 //從所有已選頂點中,找一條費用最小,且沒選的邊         for(int i=0;i<choosedNum;i++)        {            for(int j=0;j<myV[choosed[i]].size();j++)            {                edge tmp=myV[choosed[i]][j];                 if(!choose[tmp.to] && !tmp.flag && tmp.cost<cost)                {                    from=choosed[i];                    to=tmp.to;                    cost=tmp.cost;                    index=j;                 }            }        }                 myV[from][index].flag=true;  //將找到的邊標誌為已選                 //無向圖,從from->to的邊已選,那麼從to->from的邊也已選         for(int k=0;k<myV[to].size();k++)        {            if(myV[to][k].to==from)            {                myV[to][k].flag=true;                break;            }        }                choosed[choosedNum++]=to;  //將選擇的頂點放到已選點集合中         choose[to]=true;                MST+=cost;   //最小產生樹費用增加     }        printf("%d\n",MST);}        int main(){    while(scanf("%d%d",&nodeNum,&edgeNum)==2)  //輸入圖的點數、邊數     {        storeMap();                 prime();    }        system("pause");    return 0;} 

 

測試執行個體:

1、圖形:

2、輸入及結果:

 

問題:

如何利用prime演算法求解有向圖的MST?

先留在這吧。。。

 

 

 

 

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.