最小生成樹和次小生成樹


最小生成樹和次小生成樹定義:
生成樹:圖G的生成樹包含原圖中的全部頂點n,和n-1條邊.
最小生成樹就是所有生成樹中邊權和最小的.

2 那么如何求最小生成樹呢?
介紹兩種基於貪心的算法:

1.prim算法

    設圖G =(V,E),其生成樹的頂點集合為U。

  ①、把v0放入U。

  ②、在所有u∈U,v∈V-U的邊(u,v)∈E中找一條最小權值的邊,加入生成樹。

  ③、把②找到的邊的v加入U集合。如果U集合已有n個元素,則結束,否則繼續執行②。

2.kruskal算法
      首先將所有邊按邊權排序,然后按照邊權從小到大依次處理.這里要用到並查集的思想,假設已有點集U,現在正在處理邊i->j,如果i,j已在

U中則處理下一條邊,否則將i,j加入並查集中.繼續處理下一條邊,直到有n-1條邊為止.

 

3 次小生成樹
次小生成樹可由最小生成樹換一條邊得到

算法:
1)先用prim求出最小生成樹T,在prim的同時,用一個矩陣max[u][v]記錄在樹中連接u-v的路徑中權值最大的邊.
2)枚舉所有不在T中的邊u-v,加入邊u-v,刪除權值為max[u][v]的邊,不斷枚舉找到次小生成樹.

次小生成樹的模板:
#include<iostream>
using namespace std;
const int INF=0x3f3f3f3f;
int g[110][110],dist[110],mmax[110][110];
int pre[110];
bool mark[110];
bool connect[110][110];
int mst,mint;
int n,m;
int prim()
{
       int res=0,fa,p,min,i,j;
       memset(mmax,0,sizeof(mmax));
       for(i=1;i<=n;i++)
       {
              dist[i]=g[1][i];
              pre[i]=1;
              mark[i]=false;
       }
       dist[1]=0;
       mark[1]=true;
       for(i=1;i<n;i++)
       {
              p=-1;min=INF;
              for(j=1;j<=n;j++)
              {
                     if(!mark[j]&&dist[j]<min)
                     {
                            p=j;
                            min=dist[j];
                     }
              }
              if(p==-1) return res;
              mark[p]=true;
              res+=dist[p];
              fa=pre[p];
              connect[fa][p]=false;
              connect[p][fa]=false;
              mmax[fa][p]=min;
              for(j=1;j<=n;j++)
                     mmax[j][p]=(mmax[fa][p]>mmax[j][fa])?mmax[fa][p]:mmax[j][fa];
              for(j=1;j<=n;j++)
              {
                     if(!mark[j]&&dist[j]>g[p][j])
                     {
                            dist[j]=g[p][j];
                            pre[j]=p;
                     }
              }
       }
       return res;
}

int main()
{
       int tc;
    //freopen("1.txt","r",stdin);
       scanf("%d",&tc);
       while(tc--)
       {
              scanf("%d %d",&n,&m);
              memset(g,INF,sizeof(g));
              memset(connect,false,sizeof(connect));
              while(m--)
              {
                     int u,v,c;
                     scanf("%d %d %d",&u,&v,&c);
                     g[u][v]=c;
                     g[v][u]=c;
                     connect[u][v]=true;
                     connect[v][u]=true;
              }
              mst=prim();
              int i,j;
              bool flag=false;
              for(i=1;i<=n;i++)
                     for(j=1;j<=n;j++)
                     {
                            if(connect[i][j]==false||g[i][j]==INF)
                                   continue;
                            if(g[i][j]==mmax[i][j])
                            {
                                   flag=true;
                                   break;
                            }
                     }
              if(flag)
                     printf("Not Unique!\n");
              else
                     printf("%d\n",mst);
       }
       return 0;
}
 

 


免責聲明!

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



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