次小生成树(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 }

 

posted @ 2013-02-23 00:11  Missa  阅读(290)  评论(0编辑  收藏  举报