poj 1679 判断MST是不是唯一的 (次小生成树)
判断MST是不是唯一的 如果是唯一的 就输出最小的权值和 如果不是唯一的 就输出Not Unique!
次小生成树就是第二小生成树 如果次小生成树的权值和MST相等 那么MST就不是唯一的
法一:
先求出最小的权值和 然后一条边一条边的删
先标记MST中所使用的边 删边就是屏蔽这条边后 再对剩下的边(不管这些边是否被标记)求MST 如果最后的权值和 与开始算出的最小的那个 相等 就说明不是唯一的
Sample Input
2 //T
3 3 //n m
1 2 1// u v w
2 3 2
3 1 3
4 4
1 2 2
2 3 2
3 4 2
4 1 2
Sample Output
3
Not Unique!
Kruskal
1 # include <iostream> 2 # include <cstdio> 3 # include <cstring> 4 # include <algorithm> 5 # include <cmath> 6 # define LL long long 7 using namespace std ; 8 9 int n ; 10 const int MAXN=110;//最大点数 11 const int MAXM=10000;//最大边数 12 int F[MAXN];//并查集使用 13 int del[MAXM] ; 14 struct Edge 15 { 16 int u,v,w; 17 int tag ; 18 }edge[MAXM];//存储边的信息,包括起点/终点/权值 19 20 int tol;//边数,加边前赋值为0 21 void addedge(int u,int v,int w) 22 { 23 24 edge[tol].u=u; 25 edge[tol].v=v; 26 edge[tol].tag = 0 ; 27 edge[tol++].w=w; 28 } 29 bool cmp(Edge a,Edge b) 30 {//排序函数,讲边按照权值从小到大排序 31 return a.w<b.w; 32 } 33 int find(int x) 34 { 35 if(F[x]==-1)return x; 36 else return F[x]=find(F[x]); 37 } 38 int Kruskal(int d)//传入点数,返回最小生成树的权值,如果不连通返回-1 39 { 40 memset(F,-1,sizeof(F)); 41 42 int cnt=0;//计算加入的边数 43 int ans=0; 44 for(int i=0;i<tol;i++) 45 { 46 if (i == d) //屏蔽id为d的这一条边 47 continue ; 48 int u=edge[i].u; 49 int v=edge[i].v; 50 int w=edge[i].w; 51 int t1=find(u); 52 int t2=find(v); 53 if(t1!=t2) 54 { 55 ans+=w; 56 F[t1]=t2; 57 cnt++; 58 edge[i].tag = 1 ; 59 } 60 if(cnt==n-1)break; 61 } 62 if(cnt<n-1)return -1;//不连通 63 else return ans; 64 } 65 66 int main() 67 { 68 69 // freopen("in.txt","r",stdin) ; 70 int m ; 71 int T ; 72 scanf("%d" , &T) ; 73 while(T--) 74 { 75 scanf("%d %d" , &n , &m) ; 76 int i ; 77 int u , v , w ; 78 tol = 0 ; 79 while(m--) 80 { 81 scanf("%d %d %d" , &u , &v , &w) ; 82 addedge(u , v , w) ; 83 } 84 85 sort(edge,edge+tol,cmp); 86 int ans = Kruskal(-1) ; 87 88 int k = 0 ; 89 for (i = 0 ; i < tol ; i++) 90 { 91 if (edge[i].tag == 1 ) 92 { 93 del[k] = i ; 94 k++ ; 95 } 96 } 97 bool flag = 0 ; 98 int t_ans ; 99 for (i = 0 ; i < k ; i++) 100 { 101 t_ans = Kruskal(del[i]) ; 102 if (t_ans == ans) 103 { 104 flag = 1 ; 105 break ; 106 } 107 } 108 if (flag) 109 printf("Not Unique!\n") ; 110 else 111 printf("%d\n" , ans) ; 112 113 } 114 return 0 ; 115 }
法二 : Prim
1 /* 2 * 次小生成树 3 * 求最小生成树时,用数组Max[i][j]来表示MST中i到j最大边权 4 * 求完后,直接枚举所有不在MST中的边,替换掉最大边权的边,更新答案 5 * 点的编号从0开始 6 */ 7 # include <iostream> 8 # include <cstdio> 9 # include <cstring> 10 # include <algorithm> 11 # include <cmath> 12 # define LL long long 13 using namespace std ; 14 15 int n ; 16 const int MAXN=110; 17 const int INF=0x3f3f3f3f; 18 bool vis[MAXN]; 19 int lowc[MAXN]; 20 int pre[MAXN]; 21 int Max[MAXN][MAXN];//Max[i][j]表示在最小生成树中从i到j的路径中的最大边权 22 bool used[MAXN][MAXN]; 23 int cost[MAXN][MAXN]; 24 int Prim() 25 { 26 int ans=0; 27 memset(vis,false,sizeof(vis)); 28 memset(Max,0,sizeof(Max)); 29 memset(used,false,sizeof(used)); 30 vis[0]=true; 31 pre[0]=-1; 32 for(int i=1;i<n;i++) 33 { 34 lowc[i]=cost[0][i]; 35 pre[i]=0; 36 } 37 lowc[0]=0; 38 for(int i=1;i<n;i++) 39 { 40 int minc=INF; 41 int p=-1; 42 for(int j=0;j<n;j++) 43 if(!vis[j]&&minc>lowc[j]) 44 { 45 minc=lowc[j]; 46 p=j; 47 } 48 if(minc==INF)return -1; 49 ans+=minc; 50 vis[p]=true; 51 used[p][pre[p]]=used[pre[p]][p]=true; 52 for(int j=0;j<n;j++) 53 { 54 if(vis[j])Max[j][p]=Max[p][j]=max(Max[j][pre[p]],lowc[p]); 55 if(!vis[j]&&lowc[j]>cost[p][j]) 56 { 57 lowc[j]=cost[p][j]; 58 pre[j]=p; 59 } 60 } 61 } 62 return ans; 63 } 64 65 int smst(int ans) 66 { 67 int Min=INF; 68 for(int i=0;i<n;i++) 69 for(int j=i+1;j<n;j++) 70 if(cost[i][j]!=INF && !used[i][j]) 71 { 72 Min=min(Min,ans+cost[i][j]-Max[i][j]); 73 } 74 if(Min==INF)return -1;//不存在 75 return Min; 76 } 77 78 int main() 79 { 80 // freopen("in.txt","r",stdin) ; 81 int T; 82 int m; 83 scanf("%d",&T); 84 while(T--) 85 { 86 scanf("%d%d",&n,&m); 87 int u,v,w; 88 for(int i=0;i<n;i++) 89 for(int j=0;j<n;j++) 90 { 91 if(i==j)cost[i][j]=0; 92 else cost[i][j]=INF; 93 } 94 while(m--) 95 { 96 scanf("%d%d%d",&u,&v,&w); 97 u--;v--; 98 cost[u][v]=cost[v][u]=w; 99 } 100 int ans=Prim(); 101 if(ans==-1) 102 { 103 printf("Not Unique!\n"); 104 continue; 105 } 106 if(ans==smst(ans))printf("Not Unique!\n"); 107 else printf("%d\n",ans); 108 } 109 return 0; 110 }