#include<stdio.h>
#include<string.h>
#include<iostream>
#include<vector>
#define M 105
#define Max 10000000
using namespace std;
int n,m;
int map[M][M];
int max_val[M][M];//记录最小生成树中任意两点之间最大边的值
int pre[M];
bool v[M][M];
int prime()
{
int MIN[M];
bool visited[M];
int i,j,u,k;
int min,ans=0;
memset(visited,false,sizeof(visited));
memset(pre,0,sizeof(pre));
memset(max_val,0,sizeof(max_val));
for(i=1;i<=n;i++)
MIN[i]=Max;
MIN[1]=0;
for(k=0;k<n;k++)
{
min=Max;
for(i=1;i<=n;i++)
{
if(!visited[i]&&MIN[i]<min)
{
min=MIN[i];
u=i;
}
}
int p=pre[u];
max_val[p][u]=min;
v[p][u]=true;//是所求最小生成树中,标记为true
v[u][p]=true;
for(i=1;i<=n;i++)
if(visited[i])//更新所有已在最小生成树中的点到u的max_val[i][u]
max_val[i][u]=max_val[i][p]>max_val[p][u]?max_val[i][p]:max_val[p][u];
visited[u]=true;
ans+=min;
for(i=1;i<=n;i++)
{
if(!visited[i]&&MIN[i]>map[u][i])
{
MIN[i]=map[u][i];
pre[i]=u;//如果u能把MIN[i]更新,则u是i的pre
}
}
}
return ans;
}
int main()
{
int cas,i,j;
int T,T1;
bool flag;
scanf("%d",&cas);
while(cas--)
{
scanf("%d%d",&n,&m);
for(i=0;i<=n;i++)
for(j=0;j<=n;j++)
map[i][j]=Max;
for(i=0;i<m;i++)
{
int a,b,c;
scanf("%d%d%d",&a,&b,&c);
map[a][b]=map[b][a]=c;
}
memset(v,false,sizeof(v));
T=prime();//先求出一条最小生成树
flag=true;
for(i=1;i<=n;i++)
{
for(j=1;j<=n;j++)
{
if(!v[i][j]&&map[i][j]!=Max)//找一条不在最小生成树中的边(能走通)去替换最小生成树中的一条边
{
T1=T+map[i][j]-max_val[i][j];
if(T1==T)
{
flag=false;
break;
}
}
}
if(flag==false)
break;
}
if(flag)
printf("%d\n",T);
else
printf("Not Unique!\n");
}
return 0;
}
POJ 1679 次小生成树
最新推荐文章于 2022-02-25 21:57:21 发布