次小生成树(poj 1679)

次小生成树讲的比较详细的:

http://www.cppblog.com/MatoNo1/archive/2011/05/29/147627.aspx

对于prim算法的三种特殊

另外注意三种特殊情况:【1】图G不连通,此时最小生成树和次小生成树均不存在。判定方法:在扩展T的过程中找不到新的可以加入的边;【2】图G本身就是一棵树,此时最小生成树存在(就是G本身)但次小生成树不存在。判定方法:在成功求出T后,发现邻接矩阵中的值全部是无穷大;【3】图G存在平行边。这种情况最麻烦,因为这时代价最小的可行变换(-E1, +E2)中,E1和E2可能是平行边!因此,只有建立两个邻接矩阵,分别存储每两点间权值最小的边和权值次小的边的权值,然后,每当一条新边(i, j)加入时,不是将邻接矩阵中边(i, j)权值改为无穷大,而是改为连接点i、j的权值次小的边的权值。

第三点的平行边指的是什么不是很理解。难道是指重边??如果有人知道的话希望告知一下。先谢谢了。。太弱。

 

附上poj 1679的代码:(没有注意第三点的特殊情况)

View Code
  1 // File Name: 1679.cpp

  2 // Author: Missa

  3 // Created Time: 2013/2/22 星期五 22:46:03

  4 

  5 #include<iostream>

  6 #include<cstdio>

  7 #include<cstring>

  8 #include<algorithm>

  9 #include<cmath>

 10 #include<queue>

 11 #include<stack>

 12 #include<string>

 13 #include<vector>

 14 #include<cstdlib>

 15 #include<map>

 16 #include<set>

 17 using namespace std;

 18 #define CL(x,v) memset(x,v,sizeof(x));

 19 #define R(x,st,en) for(int x=st;x<en;x++)

 20 

 21 const int maxn = 105;

 22 const int inf = 0x3f3f3f3f;

 23 int g[maxn][maxn],dis[maxn];

 24 int path[maxn][maxn];//i,j路径上的最大的边权

 25 int n,m;

 26 int pre[maxn];

 27 bool vis[maxn];

 28 int prim()

 29 {

 30     R(i,1,n+1)

 31     {

 32         pre[i]=0;

 33         vis[i]=0;

 34         dis[i]=g[1][i];

 35         g[1][i]=g[i][1]=inf;

 36     }

 37     vis[1]=1;

 38     int ans=0;

 39     R(i,1,n)

 40     {

 41         int MIN = inf,flag=-1;

 42         R(j,1,n+1)

 43         {

 44             if(!vis[j] && dis[j]<MIN)

 45             {

 46                 flag=j;

 47                 MIN=dis[j];

 48             }

 49         }

 50         if(flag==-1) return -1;//不是连通的

 51         int p=pre[flag];

 52         path[p][flag]=path[flag][p]=MIN;

 53         R(j,1,n+1)

 54         {

 55             if(vis[j]&& j!=p)

 56                 path[flag][j]=path[j][flag]=max(path[p][j],MIN);

 57         }

 58         vis[flag]=1;

 59         ans+=MIN;

 60         R(j,1,n+1)

 61         {

 62             if(!vis[j] && dis[j]>g[flag][j])

 63             {

 64                 dis[j]=g[flag][j];

 65                 pre[j]=flag;

 66             }

 67         }

 68         g[flag][p]=g[p][flag]=inf;//将该边从原图中消除

 69     }

 70     return ans;

 71 }

 72 int main()

 73 {

 74     int t;

 75     scanf("%d",&t);

 76     while(t--)

 77     {

 78         int u,v,w;

 79         scanf("%d%d",&n,&m);

 80         R(i,1,n+1)

 81             R(j,1,n+1)

 82                 g[i][j]=g[j][i]=inf;

 83         R(i,1,n+1)

 84             g[i][i]=0;

 85         R(i,0,m)

 86         {

 87             scanf("%d%d%d",&u,&v,&w);

 88             g[u][v]=g[v][u]=w;

 89         }

 90         int ans=prim();

 91         if(ans==-1)

 92         {

 93             puts("0");

 94             continue;

 95         }

 96         bool ok=true;

 97         R(i,1,n+1)

 98         {

 99             if(!ok) break;

100             R(j,1,n+1)

101             {

102                 if(i!=j && g[i][j]!=inf && ans==ans-path[i][j]+g[i][j])

103                 {

104                     ok=false;

105                     break;

106                 }

107             }

108         }

109         if(ok)

110             printf("%d\n",ans);

111         else

112             puts("Not Unique!");

113     }

114     return 0;

115 }

 

你可能感兴趣的:(poj)