poj 1679 Kruskal+MST环性质
题意:在一个无向图中,若其最小生成树唯一,则输出其值;若不唯一则输出“Not Unique!”。
《算法:C语言实现》这本书将MST有两个重要性质:割性质和环性质。本题则用到了MST的环性质。也就是说在一个无向连通图中可以将边分为MST上的边和非MST上的边,若将非MST上的边e加入MST中一定会形成一个环。所以先用Kruskal算法求出MST,然后以e的一个端点开始在MST上进行深搜,找到到达另一个端点路径,查看这条路径上边的权值是否有和e的权值相等的。若有则不是唯一的,若将每个e都测试一遍都没有和e的权值相等的则是唯一的。这样说够通俗易懂了吧……然而我看到网上很多人用次小生成树的解法来做,这种解法当然是正确的。但本题只是让判断唯一不唯一,本人认为没必要那样做,我的思路已经说过了,以下是我的代码:
#include<iostream>
#include<cstring>
#include<vector>
using namespace std;
struct node
{
int start;
int end;
int value;
};
struct Adjvex
{
int v;
int value;
};
int root[101],wight[101],visit[101];
node ss[10001],tt[10001];
vector <Adjvex> map[101];
bool flag;
int cmp(const void* a,const void * b)
{
return ((node *)a)->value-((node*)b)->value;
}
int find(int i)
{
while(root[i]!=i)
i=root[i];
return i;
}
int dfs(int s,int t,int w)//搜索环路径
{
int j;
visit[s]=1;
if(s==t) return 1;
for(j=0;j<map[s].size();j++)
if(!visit[map[s][j].v] && dfs(map[s][j].v,t,w))
{
if(map[s][j].value==w) flag=true;
return 1;
}
//visit[s]=0;
return 0;
}
int Union(int s,int t)
{
if(wight[s]>=wight[t])
{
root[t]=s;
wight[s]+=wight[t];
}
else
{
root[s]=t;
wight[t]+=wight[s];
}
return 0;
}
int add(node s)//构造MST的数据结构,搜索时用
{
Adjvex e={s.end,s.value};
map[s.start].push_back(e);
e.v=s.start;
map[s.end].push_back(e);
return 0;
}
int main()
{
int i,k,m,n,N,sum,s,t,count;
cin>>n;
while(n--)
{
cin>>m>>k;
for(i=0;i<k;i++)
cin>>ss[i].start>>ss[i].end>>ss[i].value;
qsort(ss,k,sizeof(ss[0]),cmp);
for(i=1;i<=m;i++)
{
root[i]=i; wight[i]=1;
}
sum=N=count=0;
for(i=0;i<k;i++)
{
s=find(ss[i].start);
t=find(ss[i].end);
if(s==t)
{
tt[N++]=ss[i]; continue;
}
Union(s,t);
add(ss[i]);
sum+=ss[i].value;
//if(count++>=m-1) break;
}
for(flag=false,i=0;i<N;i++)
{
memset(visit,0,sizeof(visit));
dfs(tt[i].start,tt[i].end,tt[i].value);
if(flag) break;
}
if(flag)
cout<<"Not Unique!"<<endl;
else
cout<<sum<<endl;
for(i=0;i<=m;i++)
map[i].clear();
}
return 0;
}
浙公网安备 33010602011771号