AC通道:http://vjudge.net/problem/POJ-1679
【题目大意】
共T组数据,对于每组数据,给你一个n个点,m条边的图,设图的最小生成树为MST,次小生成树为ans,若MST=ans,输出Not Unique!,否则输出MST
【题解】
很明确,先求MST再求ans。
关于求次小生成树,我打算写一个总结,先留个坑。
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<ctime>
#include<algorithm>
using namespace std;
const int INF=~0u>>2;//正无穷
struct node{int x,y,v;}E[100010];
struct Node{int y,next,v;}e[200010];
int T,n,m,len,mst,ans(INF),Link[110],f[110],vis[110],map[110][110],flag[110][110],dp[110][110];
inline int read()
{
int x=0,f=1; char ch=getchar();
while(!isdigit(ch)) {if(ch=='-') f=-1; ch=getchar();}
while(isdigit(ch)) {x=x*10+ch-'0'; ch=getchar();}
return x*f;
}
void insert(int x,int y,int v) {e[++len].next=Link[x];Link[x]=len;e[len].y=y;e[len].v=v;}
int find(int x) {return f[x]==x?x:f[x]=find(f[x]);}
bool cmp(node a,node b) {return a.v<b.v;}
void Kruskal()
{
sort(E+1,E+m+1,cmp);
for(int i=1;i<=m;i++)
{
int x=find(E[i].x),y=find(E[i].y);
if(x!=y)
{
f[x]=y;
mst+=E[i].v;
flag[E[i].x][E[i].y]=flag[E[i].y][E[i].x]=1;
}
}
for(int i=1;i<=n;i++)
for(int j=i+1;j<=n;j++)
if(flag[i][j]) {insert(i,j,map[i][j]); insert(j,i,map[j][i]);}
}
void dfs(int st,int x,int v)
{
vis[x]=1;
dp[st][x]=v;
for(int i=Link[x];i;i=e[i].next)
if(!vis[e[i].y]) dfs(st,e[i].y,max(dp[st][x],e[i].v));
}
void pre()
{
memset(Link,0,sizeof(Link));
memset(flag,0,sizeof(flag));
memset(dp,0,sizeof(dp));
len=mst=0; ans=INF;
for(int i=1;i<=n;i++) f[i]=i;
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
map[i][j]=(i==j?0:INF);
}
int main()
{
freopen("cin.in","r",stdin);
freopen("cout.out","w",stdout);
T=read();
while(T--)
{
n=read(); m=read();
pre();
for(int i=1;i<=m;i++)
{
int x=read(),y=read(),v=read();
map[x][y]=map[y][x]=v;
E[i].x=x; E[i].y=y; E[i].v=v;
}
Kruskal();
for(int i=1;i<=n;i++) {memset(vis,0,sizeof(vis)); dfs(i,i,0);}
for(int i=1;i<=n;i++)
for(int j=i+1;j<=n;j++)
if(!flag[i][j]&&map[i][j]!=INF) ans=min(ans,mst+map[i][j]-dp[i][j]);
if(ans==mst) printf("Not Unique!\n");
else printf("%d\n",mst);
}
return 0;
}