poj The Unique MST 次小生成樹(入門級)
阿新 • • 發佈:2019-01-10
#include<iostream> #include<cstdio> #include<cstring> using namespace std; #define MAX 105 const int INF=0x3f3f3f3f; int g[MAX][MAX],dist[MAX],mmax[MAX][MAX]; ///g儲存地圖 dist儲存從起點到其餘各點的距離 maxn儲存從i到j的最大邊權值 int pre[MAX]; ///pre儲存j的離它最近的是哪個點 bool mark[MAX]; ///相當於vis 用來標記該點是否已經用過 bool connect[MAX][MAX]; ///儲存i-j的那條邊是否加入了最小生成樹 false 加入 true 沒有 int mst,mint; ///mst儲存最小生成樹的權值和 int n,m; int prim() { int res=0,fa,p,min,i,j; memset(mmax,0,sizeof(mmax)); for(i=1;i<=n;i++) { dist[i]=g[1][i]; pre[i]=1; mark[i]=false; } dist[1]=0; mark[1]=true; for(i=1;i<n;i++) { p=-1;min=INF; for(j=1;j<=n;j++) { if(!mark[j]&&dist[j]<min) { p=j; min=dist[j]; } } if(p==-1) return res; mark[p]=true; res+=dist[p]; fa=pre[p]; ///找到離p最近的點 connect[fa][p]=false; connect[p][fa]=false; mmax[fa][p]=min; ///遍歷所有的點 求其餘點到p的最大權值 for(j=1;j<=n;j++) mmax[j][p]=(mmax[fa][p]>mmax[j][fa])?mmax[fa][p]:mmax[j][fa]; for(j=1;j<=n;j++) { if(!mark[j]&&dist[j]>g[p][j]) { dist[j]=g[p][j]; pre[j]=p; } } } return res; } int main() { int tc; scanf("%d",&tc); while(tc--) { scanf("%d %d",&n,&m); memset(g,INF,sizeof(g)); memset(connect,false,sizeof(connect)); while(m--) { int u,v,c; scanf("%d %d %d",&u,&v,&c); g[u][v]=c; g[v][u]=c; connect[u][v]=true; connect[v][u]=true; } mst=prim(); int i,j; bool flag=false; for(i=1;i<=n;i++) for(j=1;j<=n;j++) { ///如果i-j這條邊加入了最小生成樹 或者i-j這條路不通 continue if(connect[i][j]==false||g[i][j]==INF) continue; ///如果加入的邊和刪除的邊的大小是一樣的 說明次小生成樹的權值和等於最小生成樹的權值和 ///也就是說最小生成樹不唯一 if(g[i][j]==mmax[i][j]) { flag=true; break; } } if(flag) printf("Not Unique!\n"); else printf("%d\n",mst); } return 0; }