题意:给出一个n(n<=100)结点的图,求苗条度(最大边减最小边的值)尽量小的生成树。
分析:枚举区间求最小生成树,不断更新ans
代码:
#include <map>
#include <set>
#include <cmath>
#include <queue>
#include <stack>
#include <cstdio>
#include <vector>
#include <iomanip>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#define ll long long
#define mod 1000000007
#define mem(a) memset(a,0,sizeof(a))
using namespace std;
const int maxn = 5000 + 5 , inf = 0x3f3f3f3f ;
struct edge{
int v,e,w;
bool operator < (const edge&temp)const{
return w<temp.w;
}
};
edge edges[maxn];
int fa[maxn];
int n,m,ans,cnt;
void Init(){
for(int i = 1 ; i < maxn ; i ++)
fa[i] = i;
}
int Find(int u){return fa[u]==u?u:fa[u]=Find(fa[u]);}
void Kruskal(int L){
cnt=0;
Init();int Max = -inf,Min=inf;
for(int j= L ; j <= m ;j ++){
int v = edges[j].v;
int e = edges[j].e;
int w = edges[j].w;
int x = Find(v);
int y = Find(e);
if(x!=y){
cnt++;
fa[x] = y;
Max = max(Max,w);
Min = min(Min,w);
if(cnt==n-1){
ans = min(ans,Max-Min);
return;
}
}
}
}
int main(){
// freopen("in.txt","r",stdin);
// freopen("out.txt","w",stdout);
while(scanf("%d%d",&n,&m)!=EOF&&(n||m)){
ans = inf;
for(int i = 1 ; i <= m ; i++)
scanf("%d%d%d",&edges[i].v,&edges[i].e,&edges[i].w);
sort(edges+1,edges+m+1);
for(int i = 1 ; i <= m ; i ++){
Kruskal(i);
}
printf("%d\n",ans!=inf?ans:-1);
}
}