次小生成树(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的代码:(没有注意第三点的特殊情况)
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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 }