最小生成树和次小生成树

来源:互联网 发布:微信被加软件 编辑:程序博客网 时间:2024/06/06 02:48

最小生成树和次小生成树定义:
生成树:图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;} 


0 0
原创粉丝点击