题目链接
https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=4141
问题的意思是叫你找到一颗生成树,生成树的值定义为权重最大的一条边
Wmax
减去权重最小的一条边
Wmin
,使生成树的值最小,输入和输出看原题,顶点个数
n<=100
,边
m<(n−1)n/2
可以估算出
m<5000
.
分析
由于这道题的边数不是很大,可以用枚举的方式固定一条最小边,再找权重比他大的边用Kruskal的算法构造生成树。
简单分析一下复杂度。最小边最多小于5000种,每种情况最多找99条边。也就是说在
O(105)
界内能够找到
代码
#include<cstdio>
#include<algorithm>
#include<cstring>
#define INF 0x3f3f3f3f
#define maxe 50010
#define maxn 109
using namespace std;
int nv,ne;
struct Edge{
int u,v,w;
bool operator<(Edge& o)
{
return w<o.w;
}
}edge[maxe];
//set
int p[maxn];
int find(int a)
{
return p[a] ==a? a:p[a] = find(p[a]);
}
void union_set(int x,int y)
{
x = find(x);
y = find(y);
if(x!=y)
p[x] = y;
}
int main()
{
//freopen("H:\\c++\\file\\stdin.txt","r",stdin);
while(scanf("%d %d",&nv,&ne)&&nv)
{
for(int i=0 ; i<ne ; ++i)scanf("%d %d %d",&edge[i].u,&edge[i].v,&edge[i].w);
if(ne<nv-1){
printf("-1\n");
continue;
}
sort(edge,edge+ne);
int ans = INF;
for(int l = ne - nv+1 ; l>=0 ;--l)
{
int max = l;
int cnt=1;
//生成树
for(int i=1 ; i<=nv ; ++i )p[i] = i;
union_set(edge[l].u,edge[l].v);
while(cnt<nv-1)
{
max++;
if(max>=ne){
break;
}else
{
int x = find(edge[max].u);
int y = find(edge[max].v);
if(x!=y)
{
cnt++;
union_set(x,y);
}
}
}
if(cnt==nv-1&&ans>edge[max].w-edge[l].w)ans= edge[max].w-edge[l].w;
}
if(ans == INF)printf("-1\n");
else printf("%d\n",ans);
}
return 0;
}