模板题目,没啥可说的。
/****************************
* author:crazy_石头
* date:2014/01/18
* algorithm:次小生成树
* Pro:POJ 1679
* 次小生成树
* 求最小生成树时,用数组Max[i][j]来表示MST中i到j最大边权
* 求完后,直接枚举所有不在MST中的边,替换掉最大边权的边,更新答案
* 点的编号从0开始
***************************/
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <string>
#include <queue>
#include <vector>
using namespace std;
#define INF 1<<29
#define eps 1e-8
#define A system("pause")
#define rep(i,h,n) for(int i=(h);i<=(n);i++)
#define ms(a,b) memset((a),(b),sizeof(a))
const int maxn=100+10;
const int maxm=3000+10;
bool vis[maxn],used[maxn][maxn];
int lowc[maxn],pre[maxn],Max[maxn][maxn],ans,cost[maxn][maxn];
int test,n,m;
inline int Prim(int cost[][maxn],int n)
{
int ans=0;
ms(vis,0),ms(Max,0),ms(used,0);
vis[0]=true,pre[0]=-1;
for(int i=1;i<n;i++)
{
lowc[i]=cost[0][i];
pre[i]=0;
}
lowc[0]=0;
for(int i=1;i<n;i++)
{
int minc=INF;
int p=-1;
for(int j=0;j<n;j++)
if(!vis[j]&&minc>lowc[j])
{
minc=lowc[j];
p=j;
}
if(minc==INF) return -1;
ans+=minc;
vis[p]=true;
used[p][pre[p]]=used[pre[p]][p]=true;
for(int j=0;j<n;j++)
{
if(vis[j])
Max[j][p]=Max[p][j]=max(Max[j][pre[p]],lowc[p]);
if(!vis[j]&&lowc[j]>cost[p][j])
{
lowc[j]=cost[p][j];
pre[j]=p;
}
}
}
return ans;
}
inline int smst(int cost[][maxn],int n)
{
int Min=INF;
for(int i=0;i<n;i++)
for(int j=i+1;j<n;j++)
if(cost[i][j]!=INF&&!used[i][j])
Min=min(Min,ans+cost[i][j]-Max[i][j]);
if(Min==INF) return -1;
return Min;
}
int main()
{
scanf("%d",&test);
while(test--)
{
int u,v,w;
scanf("%d%d",&n,&m);
rep(i,0,n-1) rep(j,0,n-1) i==j?cost[i][j]=0:cost[i][j]=INF;
while(m--)//0开始
{
scanf("%d%d%d",&u,&v,&w);
u--,v--;
cost[u][v]=cost[v][u]=w;
}
ans=Prim(cost,n);
if(ans==-1)
{
printf("Not Unique!\n");
continue;
}
if(ans==smst(cost,n)) printf("Not Unique!\n");
else printf("%d\n",ans);
}
return 0;
}