題目鏈接
參考博客
希望注釋足夠清楚。。歡迎指出不足~
#include<cstdio> #include<cstring> #include<algorithm> using namespace std;const int maxn=110; const int INF=0x3f3f3f3f;int n,m; int mp[maxn][maxn]; int maxlen[maxn][maxn]; //maxlen[i][j]表示//生成樹上,從 點i到點j的所有邊中的最大邊長 int dis[maxn],pre[maxn]; //dis表示的其實是邊長 int vis[maxn]; int mst;int prim() {mst=0;vis[1]=1;for(int i=1; i<=n; i++)dis[i]=mp[1][i],pre[i]=1;for(int i=1; i<n; i++) //總共需要再加入n-1個節點 {int min_dis=INF,nx,pr;//nx表示下一個要進入MST中的結點//pr表示與nx相連的已經在MST中的結點//min_dis表示MST與V-MST間的最短距離 for(int j=1; j<=n; j++)if(!vis[j]&&dis[j]<min_dis)nx=j,min_dis=dis[nx];pr=pre[nx];mst+=mp[nx][pr]; maxlen[nx][pr]=maxlen[pr][nx]=mp[nx][pr];for(int j=1; j<=n; j++) if(vis[j]) //更新從j沿MST到nx的最小邊長 maxlen[j][nx]=maxlen[nx][j]=max(maxlen[j][pr],maxlen[nx][pr]);vis[nx]=1;for(int j=1;j<=n;j++)if(!vis[j]&&mp[nx][j]<dis[j])dis[j]=mp[nx][j],pre[j]=nx;}for(int i=1;i<n;i++)for(int j=i+1;j<=n;j++)if(pre[i]==j||pre[j]==i) //此時邊i-j在MST中 continue; else if(maxlen[i][j]==mp[i][j])//存在不止一個MST return 0;return 1; //只有一個MST }void init() {memset(mp,INF,sizeof(mp));memset(maxlen,-INF,sizeof(maxlen)); //之后要不斷取max進行更新 memset(vis,0,sizeof(vis)); }int main() {int T;scanf("%d",&T);while(T--){init();scanf("%d%d",&n,&m);for(int i=0; i<m; i++){int u,v,w;scanf("%d%d%d",&u,&v,&w);mp[u][v]=mp[v][u]=w;}if(prim()) printf("%d\n",mst);else puts("Not Unique!");} }
?