#include<cstdio>
#include<iostream>
#include<cstring>
#define L 110
#define inf 0x3f3f3f3f
using namespace std;
int dis[110],pre[110],Map[110][110],Ma[110][110];
bool use[110][110],vis[110];
int n;
int prim()
{
int i,j;
memset(vis,false,sizeof(vis));
memset(pre,-1,sizeof(pre));
memset(use,false,sizeof(use));
memset(Ma,0,sizeof(Ma));
for(i=1;i<=n;i++)
{
dis[i]=Map[1][i];
pre[i]=1;//父节点
}
dis[1]=0;
vis[1]=true;
int ma,pos;
int s=0;
for(i=1;i<n;i++)
{
ma=inf;
pos=-1;
for(j=1;j<=n;j++)
{
if(ma>dis[j]&&!vis[j])
{
ma=dis[j];
pos=j;
}
}
if(ma==inf)//注意当删边后不连通直接跳出输出->不统一
return -1;
s+=ma;
vis[pos]=true;
use[pre[pos] ][pos]=use[pos ][pre[pos] ]=true;//标记下加到树中的边
for(j=1;j<=n;j++)
{
if(vis[j])
{//选出父节点到POS间的MAX距离
Ma[pos][j]=Ma[j][pos]=max(Ma[pre[pos] ][j],dis[pos]);
}
if(!vis[j]&&dis[j]>Map[pos][j])
{
dis[j]=Map[pos][j];
pre[j]=pos;
}
}
}
return s;
}
int ans;
int f()
{
int mi=inf;
for(int i=1;i<n;i++)
{
for(int j=i+1;j<=n;j++)
{
if(Map[i][j]!=inf&&!use[i][j])//从除最小生成树中的其他的边来加到树中
{
mi=min(mi,ans+Map[i][j]-Ma[i][j]);
}
}
}
if(mi==inf)
return -1;
return mi;
}
int main()
{
int m,i,j,k;
int cla;
scanf("%d",&cla);
while(cla--)
{
int a,b,c;
scanf("%d%d",&n,&m);
for(i=1;i<=n;i++)
{
for(j=1;j<=n;j++)
{
if(i!=j)
Map[i][j]=inf;
else
Map[i][j]=0;
}
}
for(i=0;i<m;i++)
{
scanf("%d%d%d",&a,&b,&c);
if(Map[a][b]>c)
{
Map[a][b]=Map[b][a]=c;
}
}
ans=prim();
if(ans==-1)
{
printf("Not Unique!\n");
continue;
}
if(ans==f())
{
printf("Not Unique!\n");
}
else
printf("%d\n",ans);
}
return 0;
}

本文探讨了最小生成树算法及其应用,并通过实例展示了如何计算最优路径,涉及图论、算法实现及复杂性分析。
1万+

被折叠的 条评论
为什么被折叠?



