题目链接
参考博客
希望注释足够清楚。。欢迎指出不足~
#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!");} }