思路:
在prim算法中,假设有a,b,c三个点。当更新加入c点时,若ac和bc的权值都为最小值,说明最小生成树不唯一。
理由很简单,当存在两个最小权值时,abc和acb都是最小生成树。
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<queue>
#include<cstring>
using namespace std;
const int N=105;
#define inf 0x3f3f3f3f
int n,m,vis[N];
int dis[N],ma[N][N],cost,flag;void prim(){for(int i=1;i<=n;i++){dis[i]=ma[1][i];vis[i]=0;}dis[1]=0;vis[1]=1;for(int i=1;i<=n;i++){int mi=inf;int mb;for(int j=1;j<=n;j++){if(!vis[j]&&dis[j]<mi){mi=dis[j];mb=j;}}if(mi==inf) break;int ce=0;for(int j=1;j<=n;j++){if(vis[j]&&ma[mb][j]==mi)//检查最小权值的边个数,若超过一个则最小生成树不唯一ce++;}if(ce>1) {flag=0;return;}vis[mb]=1;cost+=dis[mb];for(int i=1;i<=n;i++){if(!vis[i]&&ma[mb][i]<dis[i]){dis[i]=ma[mb][i];}}}}
int main(){int T;scanf("%d",&T);while(T--){cost=0;scanf("%d%d",&n,&m);int a,b,c;memset(ma,0x3f3f3f3f,sizeof(ma));for(int i=1;i<=m;i++){scanf("%d%d%d",&a,&b,&c);ma[a][b]=ma[b][a]=c;}flag=1;prim(); if(flag)printf("%d\n",cost);else puts("Not Unique!");}return 0;
}