题目大意 给出一个n结点的图,求苗条度(最大边减最小边的值)尽量小的生成树
先把m条边排序 每次m²的枚举L和R,表示取哪些边。
可以加剪枝,必须满足W[R]-W[L]<ans才进行操作,W[i]为第i条边的权值,ans为当前能得出的最小苗条度。
且把L作为一重循环时,当有R满足条件,进行操作之后,就应该取下一个L。
tirck点 当n=2 m=1是特判一下即可
#include <iostream>
#include <cstring>
#include <string>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <vector>
#include <queue>
#include <map>
#include<set>
#include<stack>
#define bug puts("bugbugbug");
using namespace std;
typedef long long ll;
const int maxm=4000005;
const int inf=10000000;
int f[2005];
int n,m;
struct node
{
int x, y, v;
bool operator<(const node &b)const
{
if(this->v!=b.v)
return (this->v<b.v);
if(this->x!=b.x)
return (this->x<b.x);
return (this->y<b.y);
}
} e[maxm];
int find(int x)
{
return f[x]= f[x]==x?x:find(f[x]);
}
int Kruscal(int a,int b)
{
int cnt = n;
for(int i = 0; i <= n; i++) f[i] = i;
for (int i = a; i <= b; i++)
{
int x = find(e[i].x);
int y = find(e[i].y);
if (x != y)
{
f[x] = y;
cnt--;
if (cnt == 1) break;
}
}
if(cnt!=1)return 0;
return 1;
}
int main()
{
int m;
while(scanf("%d%d",&n,&m)&&n+m)
{
for(int i=0; i<m; i++)
scanf("%d%d%d",&e[i].x,&e[i].y,&e[i].v);
if(n==2&&m==1)
{
puts("0");
continue;
}
sort(e, e + m);
int ans=inf;
for(int i=0; i<m; i++)
for(int j=i+1; j<m; j++)
if(e[j].v-e[i].v<ans&&Kruscal(i,j))
{
ans=e[j].v-e[i].v;
break;
}
if(ans==inf)
puts("-1");
else
printf("%d\n",ans);
}
}