http://poj.org/problem?id=1679
Description
Input
Output
Sample Input
2 3 3 1 2 1 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!
/** poj 1679 次小生成树 题目大意:给定一个无向图,问它的最小生成树是否唯一 解题思路:利用prim算法求出最小生成树,并且用mlen数组标记在已知的生成树上i和j两点之间的经过边的最大权值,最后枚举所有没有在最小生成树上的 边,加上该边,并且减去对应mlen,得到的结果就是必须用当前边的最小生成树,所有之中最小的就是次小生成树的大小,和最小生成树进行比较即可 */ #include <stdio.h> #include <iostream> #include <string.h> #include <algorithm> #include <math.h> using namespace std; const int maxn=1010; struct note { int x,y,z; }p[maxn]; int a[maxn][maxn],dis[maxn]; int pre[maxn],n,m; int flag[maxn][maxn],vis[maxn]; int mlen[maxn][maxn]; int prim(int u) { int sum=0; memset(flag,0,sizeof(flag)); memset(vis,0,sizeof(vis)); memset(mlen,0,sizeof(mlen)); for(int i=1; i<=n; i++) { dis[i]=a[u][i]; pre[i]=u; } vis[u]=1; for(int i=1; i<n; i++) { int minn=0x3f3f3f3f; int v=-1; for(int j=1; j<=n; j++) { if(!vis[j]&&dis[j]<minn) { v=j; minn=dis[j]; } } if(v!=-1) { sum+=dis[v]; flag[v][pre[v]]=flag[pre[v]][v]=1; vis[v]=1; for(int k=1; k<=n; k++) { if(vis[k]&&k!=v) { mlen[v][k]=mlen[k][v]=max(mlen[k][pre[v]],dis[v]); } if(!vis[k]&&a[v][k]<dis[k]) { dis[k]=a[v][k]; pre[k]=v; } } } } return sum; } int main() { int T; scanf("%d",&T); while(T--) { scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) { for(int j=1;j<=n;j++) { if(i==j) a[i][j]=0; else a[i][j]=0x3f3f3f3f; } } for(int i=1; i<=m; i++) { int x,y,w; scanf("%d%d%d",&x,&y,&w); a[x][y]=a[y][x]=w; } int ans=prim(1); int cnt=0x3f3f3f3f; for(int i=1;i<=n;i++) { for(int j=i+1;j<=n;j++) { if(a[i][j]!=0x3f3f3f3f&&!flag[i][j]) { cnt=min(cnt,ans-mlen[i][j]+a[i][j]); } } } if(cnt!=ans) printf("%d\n",ans); else puts("Not Unique!"); } return 0; }