题目链接:http://poj.org/problem?id=1679
题目大意:就是给你一个图,然后让你判断该图的MST是否是唯一的
大概思路:就是用Kruskal或者prim第一次求出MST,并且标记第一次MST中有权值一样的边。如果发现该图没有相同的权值的边,那该图的MST是唯一的。否则依次删除MST中有被标记的权值相同的边并进行另一次MST,如果这次求的的MST的总权值和第一次是一样的那表示该图的MST是不唯一的,如果依次删除相同的权值的边后的MST的权值均与第一次的MST的权值不同那表示该图的MST是唯一的。
参考代码:
#include<iostream>
using namespace std;
#include<algorithm>
#define MAXN 105
int parent[MAXN],n,m;
struct node
{
int u,v,w;
int equal;//改变是否唯一 是为0 否为1
int use;//改变是否使用,是为1 否为0
int del;//改变是否被删除 是为1 否为0
}map[10000];
bool first;//记录是第一次就是MST中的边
void UFset()
{
for(int i=0;i<n;i++)
parent[i]=-1;
}
int Find(int x)
{
int s,tmp;
for(s=x;parent[s]>=0;s=parent[s]);
while(s!=x)
{
tmp=parent[x];
parent[x]=s;
x=tmp;
}
return s;
}
void Union(int R1,int R2)
{
int r1=Find(R1),r2=Find(R2);
int tmp=parent[r1]+parent[r2];
if(parent[r1]>parent[r2])
{
parent[r1]=r2;
parent[r2]=tmp;
}
else
{
parent[r2]=r1;
parent[r1]=tmp;
}
}
bool cmp(node a,node b)
{
return a.w<b.w;
}
int Kruskal()
{
int sum=0;
int num=0;
int u,v,i;
UFset();
for(i=0;i<m;i++)
{
if(map[i].del==1)//如果该边是被删除的了,那就不处理
continue;
u=map[i].u,v=map[i].v;
if(Find(u)!=Find(v))
{
sum+=map[i].w;
if(first)
map[i].use=1;//记录该边已经在MST中了
Union(u,v);
num++;
}
if(num>n)
break;
}
return sum;
}
int main()
{
int T,i,a,b,c;
cin>>T;
while(T--)
{
cin>>n>>m;
for(i=0;i<m;i++)
{
cin>>a>>b>>c;
map[i].u=a-1;map[i].v=b-1;map[i].w=c;
map[i].equal=map[i].use=map[i].del=0;//初始化
}
for(i=0;i<m;i++)//标记权值相同的边
{
for(int k=0;k<m;k++)
{
if(i==k)
continue;
if(map[i].w==map[k].w)
map[i].equal=1;
}
}
sort(map,map+m,cmp);
first=true;
int weight1=Kruskal(),weight2;//第一次求MST
first=false;
int j;
for( j=0;j<m;j++)//依次删除相同的权值的边并进行MST的求解
{
if(map[j].use&&map[j].equal)
{
map[j].del=1;
weight2=Kruskal();
if(weight1==weight2)
{
cout<<"Not Unique!"<<endl;
break;
}
map[j].del=0;
}
}
if(j>=m)
cout<<weight1<<endl;
}
return 0;
}