次小生成树
次小生成树可由最小生成树换一条边得到。
其生成过程:
#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
const int N=1005;
const int INF=1<<30;
bool vis[N],used[N][N];
int dist[N],pre[N];
int map[N][N],medge[N][N];
int ans1,ans2,n,m;
void Init()
{
memset(vis,0,sizeof(vis));
memset(pre,0,sizeof(pre));
memset(dist,0,sizeof(dist));
memset(used,0,sizeof(used));
memset(medge,0,sizeof(medge));
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
map[i][j]=INF;
}
int Prime()
{
int ans=0;
for(int i=1;i<=n;i++)
{
dist[i]=map[1][i];
pre[i]=1;
}
vis[1]=1;
dist[1]=0;
for(int i=1;i<=n;i++)
{
int k=0;
int minval=INF;
for(int j=1;j<=n;j++)
{
if(!vis[j]&&dist[j]<minval)
{
minval=dist[j];
k=j;
}
}
vis[k]=1;
pre[k]=i;
used[i][k]=0;
used[k][i]=0;
ans+=dist[k];
for(int j=1;j<=n;j++)
{
if(vis[j])
medge[k][j]=medge[j][k]=max(medge[pre[k]][j],map[pre[k]][k]);
if(!vis[j]&&map[k][j]<dist[j])
{
dist[j]=map[k][j];
pre[j]=k;
}
}
}
return ans;
}
int Second_Prime()
{
int ans=INF;
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
if(used[i][j])
ans=min(ans,ans1+map[i][j]-medge[i][j]);
return ans;
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
scanf("%d%d",&n,&m);
Init();
if(n == 0) break;
for(int i=1;i<=m;i++)
{
int u,v,w;
scanf("%d%d%d",&u,&v,&w);
map[u][v]=map[v][u]=w;
used[u][v]=used[v][u]=1;
}
ans1=Prime();
ans2=Second_Prime();
if(ans1==ans2) puts("Not Unique!");
else printf("%d\n",ans1);
}
return 0;
}