POJ 1679 The Unique MST(次小生成树模板题)
首先,不难证明次小生成树的连边与最小生成树一定不相同
因此,我们可以枚举每一条在最小生成树上的边
在剩下的边的集合中再求最小生成树
也就是再对n-1个缺一条边的图求最小生成树
对于严格次小生成树
找出n-1棵树中找到权值>原最小生成树且最小的
对非严格次小生成树
找出n-1棵树中找到权值>=原最小生成树且最小的
#include <iostream> #include <cstring> #include <cstdio> #include <algorithm> using namespace std; const int INF=0x3f3f3f3f; const int maxn=110; bool vis[maxn]; int lowc[maxn]; int cost[maxn][maxn]; int pre[maxn]; int MAX[maxn][maxn]; bool used[maxn][maxn]; int prim(int cost[][maxn],int n) { int ans=0; memset(vis,0,sizeof(vis)); memset(MAX,0,sizeof(MAX)); memset(used,0,sizeof(used)); vis[0]=1; pre[0]=-1; for(int i=1;i<n;i++) { lowc[i]=cost[0][i]; pre[i]=0; } lowc[0]=0; for(int i=1;i<n;i++) { int minc=INF; int p=-1; for(int j=0;j<n;j++) { if(!vis[j]&&minc>lowc[j]) { minc=lowc[j]; p=j; } } if(minc==INF) return -1; ans+=minc; vis[p]=1; used[p][pre[p]]=used[pre[p]][p]=1; for(int j=0;j<n;j++) { if(vis[j]) MAX[j][p]=max(MAX[j][pre[p]],lowc[p]); if(!vis[j]&&lowc[j]>cost[p][j]) { lowc[j]=cost[p][j]; pre[j]=p; } } } return ans; } int ans; int smst(int cost[][maxn],int n) { int Min=INF; for(int i=0;i<n;i++) { for(int j=i+1;j<n;j++) { if(cost[i][j]!=INF&&!used[i][j]) { Min=min(Min,ans+cost[i][j]-MAX[i][j]); } } } if(Min==INF) return -1; return Min; } int main() { int T; int n,m; scanf("%d",&T); while(T--) { scanf("%d%d",&n,&m); int u,v,w; for(int i=0;i<n;i++) for(int j=0;j<n;j++) { if(i==j)cost[i][j]=0; else cost[i][j]=INF; } while(m--) { scanf("%d%d%d",&u,&v,&w); u--;v--; cost[u][v]=cost[v][u]=w; } ans=prim(cost,n); if(ans==-1) { printf("Not Unique!\n"); continue; } if(ans==smst(cost,n))printf("Not Unique!\n"); else printf("%d\n",ans); } return 0; }