题目描述
求所有生成树中最大边权与最小边权差最小的,输出它们的差值。
解题思路
紫书P358,原来以为很难,看来书发现是个水题。虽然紫书上已经说的很清楚了,不过还是打算稍微写下:
按权值从小到大将边排序,那么对于排序后的边集区间
[
l
,
r
]
[l,r]
[l,r]如果能把点全部连通,那么对于这个边集区间的答案
W
[
r
]
−
W
[
l
]
W[r]-W[l]
W[r]−W[l]。枚举所有边集区间,复杂度
O
(
m
2
)
O(m^2)
O(m2),在加上判断连通可以用并查集,由于并查集有路径压缩,复杂度比log还低,所以不会超时。
代码
#include <bits/stdc++.h>
using namespace std;
struct node{
int a,b,c;
bool operator < (const node & rs) const {
return c<rs.c;
}
}edge[10005];
int n,m,fa[105];
int findf(int x)
{
if(fa[x]==x)return x;
return fa[x]=findf(fa[x]);
}
int main(){
while(cin>>n>>m&&n)
{
for(int i=0;i<m;i++)
scanf("%d%d%d",&edge[i].a,&edge[i].b,&edge[i].c);
sort(edge,edge+m);
int ans=-1;
for(int l=0;l<m;l++)
{
for(int i=0;i<=n;i++)
fa[i]=i;
int cnt=0//当前添加了几条边
for(int i=l;i<m;i++)
{
int f1=findf(edge[i].a);
int f2=findf(edge[i].b);
if(f1!=f2)
{
cnt++;
fa[f1]=f2;
}
if(cnt==n-1)//当添加了n-1条边,图一定连同
{
if(ans==-1||ans>edge[i].c-edge[l].c)
ans=edge[i].c-edge[l].c;
break;
}
}
}
printf("%d\n",ans);
}
return 0;
}