【POJ 1679】The Unique MST(次小生成树)
找出最小生成树,同时用Max[i][j]记录i到j的唯一路径上最大边权。然后用不在最小生成树里的边i-j来替换,看看是否差值为0。
#include <algorithm> #include <cstdio> #include <cstring> using namespace std; const int N=101; const int INF=0x3f3f3f3f; int n,m,ans,s; int lowc[N],vis[N],g[N][N]; int Max[N][N],fa[N],used[N][N]; int Prim(){ int ans=0; memset(Max,0,sizeof Max); memset(used,0,sizeof used); memset(vis,0,sizeof vis); vis[0]=1; for(int i=1;i<n;i++){ lowc[i]=g[0][i];fa[i]=0; } for(int i=1;i<n;i++){ int p=0; while(vis[p])p++; for(int j=p+1;j<n;j++) if(!vis[j] && lowc[j]<lowc[p]) p=j; if(lowc[p]==INF)return -1;//原图不连通 ans+=lowc[p]; vis[p]=1; used[p][fa[p]]=used[fa[p]][p]=1; for(int j=0;j<n;j++) if(vis[j]) Max[j][p]=Max[p][j]=max(Max[j][fa[p]],lowc[p]); else if(g[p][j]<lowc[j]){ lowc[j]=g[p][j]; fa[j]=p; } } return ans; } int main(){ int t; scanf("%d",&t); while(t--){ memset(g,INF,sizeof g); scanf("%d%d",&n,&m); while(m--){ int u,v,w; scanf("%d%d%d",&u,&v,&w); u--;v--; g[u][v]=g[v][u]=w; } ans=Prim(); s=INF; for(int i=0;i<n;i++) for(int j=i+1;j<n;j++) if(g[i][j]!=INF&&!used[i][j]) s=min(s,g[i][j]-Max[i][j]); if(ans==-1||s==0) puts("Not Unique!"); else printf("%d\n",ans); } return 0; }
wa了好几发,原因是,s初始化为ans,而如果ans本身就是0的话,应该是唯一的最小生成树。
┆凉┆暖┆降┆等┆幸┆我┆我┆里┆将┆ ┆可┆有┆谦┆戮┆那┆ ┆大┆始┆ ┆然┆
┆薄┆一┆临┆你┆的┆还┆没┆ ┆来┆ ┆是┆来┆逊┆没┆些┆ ┆雁┆终┆ ┆而┆
┆ ┆暖┆ ┆如┆地┆站┆有┆ ┆也┆ ┆我┆ ┆的┆有┆精┆ ┆也┆没┆ ┆你┆
┆ ┆这┆ ┆试┆方┆在┆逃┆ ┆会┆ ┆在┆ ┆清┆来┆准┆ ┆没┆有┆ ┆没┆
┆ ┆生┆ ┆探┆ ┆最┆避┆ ┆在┆ ┆这┆ ┆晨┆ ┆的┆ ┆有┆来┆ ┆有┆
┆ ┆之┆ ┆般┆ ┆不┆ ┆ ┆这┆ ┆里┆ ┆没┆ ┆杀┆ ┆来┆ ┆ ┆来┆