int find(int x)//找寻不会形成环的边,如果一条边的两个顶点有相同的父节点,则会出现环
{
return father[x]==x?father[x]:father[x]=find(father[x]);// 如图,若AB被选中,BC也被选中,扫到CA时因为A与C的父节点相同而跳过}
避免成环。
int cmp(Edge a , Edge b)
{
return a.cap<b.cap;
}
void kruskal() {
sort(edge,edge+m,cmp); //按照边的权值排序
for(int i=0;i<m;i++)
{
makeSet();
int len=0,temp;
for(int j=i;j<m;j++)
{
int fatherU=find(edge[j].u);
int fatherV=find(edge[j].v);
if(fatherU!=fatherV){
len++;
father[fatherV]=fatherU;
if(len==n-1){
temp=edge[j].cap-edge[i].cap;
break;
}
}
}
if(temp<ans)
{
ans=temp;
}
}
}
例题 POJ 3522
题意:找到生成树中最大权值与最小权值的最小值
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define maxn 110
#define INF 0x3f3f3f3f
using namespace std;
struct Edge{
int u,v;
int cap;
}edge[maxn*maxn];
int n,m,ans,father[maxn];
void makeSet()
{
for(int i=1;i<=n;i++)
{
father[i]=i;
}
}
int find(int x)
{
return father[x]==x?father[x]:father[x]=find(father[x]);
}
int cmp(Edge a , Edge b)
{
return a.cap<b.cap;
}
void kruskal()
{
sort(edge,edge+m,cmp);
for(int i=0;i<m;i++)
{
makeSet();
int len=0,temp;
for(int j=i;j<m;j++)
{
int fatherU=find(edge[j].u);
int fatherV=find(edge[j].v);
if(fatherU!=fatherV){
len++;
father[fatherV]=fatherU;
if(len==n-1){
temp=edge[j].cap-edge[i].cap;
break;
}
}
}
if(temp<ans)
{
ans=temp;
}
}
}
int main()
{
while(~scanf("%d%d",&n,&m),n+m)
{
for(int i=0;i<m;i++)
{
scanf("%d%d%d",&edge[i].u,&edge[i].v,&edge[i].cap);
}
ans=INF;
kruskal();
if(ans!=INF)
{
printf("%d\n",ans);
}else{
printf("-1\n");
}
}
return 0;
}