POJ-1679 The Unique MST 次小生成树
题目链接:http://poj.org/problem?id=1679
求是否存在多个最小生成树,其实就是求次小生成树的权值是否等于最小生成树。
最小生成树的两个性质:
1.切割性质:假定所有边权值不相等,设S为即非空集合也非全集V的子集,边e是满足一个端点在S内,另一个端点不在S内的所有边中权值最小的一个,则图G的所有生成树均包含e。
2.回路性质:假定所有边权值不相等,设C是图G中的任意回路,边e是C上权值最大的边,则图G的所有生成树均不包含e。
求次小生成树一遍朴素的做法就是枚举最小生成树中的边删去,然后再在图上求最小生成树,复杂度O(n*m*lgm);对于稀疏图来说,复杂度还是不高的。还有一种更好的方法,就是利用性质2。在最小生成树上家一条边u-v之后,图上会出现一条回路,因此删除的必须在最小生成树上u-v的路径上,而且是这条路径上的最长边。可以证明,次小生成树一定可以由最小生成树加一条边再删一条边得到(边交换)。因此只需求出”每对节点之间的最小瓶颈路“之后,然后依次枚举m条边就可以了。总复杂度O(n^2);
1 //STATUS:C++_AC_0MS_368KB 2 #include<stdio.h> 3 #include<stdlib.h> 4 #include<string.h> 5 #include<math.h> 6 #include<iostream> 7 #include<string> 8 #include<algorithm> 9 #include<vector> 10 #include<queue> 11 #include<stack> 12 using namespace std; 13 #define LL __int64 14 #define pdi pair<double,int> 15 #define Max(a,b) ((a)>(b)?(a):(b)) 16 #define Min(a,b) ((a)<(b)?(a):(b)) 17 #define mem(a,b) memset(a,b,sizeof(a)) 18 #define lson l,mid,rt<<1 19 #define rson mid+1,r,rt<<1|1 20 const int N=110,M=1000000,INF=0x3f3f3f3f,MOD=1999997; 21 const LL LLNF=0x3f3f3f3f3f3f3f3fLL; 22 const double DNF=100000000; 23 24 struct Edge{ 25 int u,v,w; 26 }e[N*N]; 27 int p[N],vis[N],mst[N][N],d[N][N],w[N][N]; 28 int T,n,m,mt; 29 30 int cmp(const Edge& a,const Edge& b) 31 { 32 return a.w<b.w; 33 } 34 35 int find(int x){return p[x]==x?x:p[x]=find(p[x]);} 36 37 int dfs(int& s,int u,int max) 38 { 39 int v; 40 for(v=1;v<=n;v++){ 41 if(mst[u][v] && !vis[v]){ 42 vis[v]=1; 43 d[s][v]=Max(max,w[u][v]); 44 dfs(s,v,d[s][v]); 45 } 46 } 47 return 0; 48 } 49 50 int Kruskal() 51 { 52 int i,j,x,y,sum=0; 53 for(i=1;i<=n;i++)p[i]=i; 54 sort(e,e+m,cmp); 55 mem(mst,0); 56 for(i=0;i<m;i++){ 57 x=find(e[i].u); 58 y=find(e[i].v); 59 if(x!=y){ 60 sum+=e[i].w; 61 p[y]=x; 62 mst[e[i].u][e[i].v]=mst[e[i].v][e[i].u]=1; 63 } 64 } 65 return sum; 66 } 67 68 int main() 69 { 70 // freopen("in.txt","r",stdin); 71 int i,j,a,b,c,ok,ans; 72 scanf("%d",&T); 73 while(T--) 74 { 75 mt=0; 76 mem(w,-1); 77 scanf("%d%d",&n,&m); 78 for(i=0;i<m;i++){ 79 scanf("%d%d%d",&a,&b,&c); 80 w[a][b]=w[b][a]=c; 81 e[i].u=a,e[i].v=b,e[i].w=c; 82 } 83 84 ans=Kruskal(); 85 for(i=1;i<=n;i++){ 86 mem(vis,0);vis[i]=1; 87 dfs(i,i,0); 88 } 89 for(i=0,ok=1;i<m;i++) 90 if(d[e[i].u][e[i].v]==e[i].w && 91 !mst[e[i].u][e[i].v]){ok=0;break;} 92 93 if(ok)printf("%d\n",ans); 94 else printf("Not Unique!\n"); 95 } 96 return 0; 97 }