希望注释足够清楚。。欢迎指出不足~
#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!"); } }