题意
求最苗条生成树(即最大边权值-最小边权值)最小的生成树, 若能构成最苗条生成树输出苗条度, 否则输出-1
思路
复健题目一个月没做题第一发就是AC
思路很简单的Kruskal算法求最小生成树
遍历枚举开始位置,当生成n-1条边时记录苗条度即可
AC代码
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
using namespace std;
int n, m;
const int maxn = 105;
const int maxm = 5000;
const int INF = 0x3f3f3f3f;
int f[maxn];
//typedef unsigned long long ULL;
void init(){
for( int i = 0; i <= n; i++ )
f[i] = i;
}
int _find(int a){
if( f[a] == a ) return f[a];
else return f[a] = _find(f[a]);
}
void _union(int a, int b){
int aa = _find(a), bb = _find(b);
if(aa != bb){
f[bb] = aa;
}
}
struct edge{
int fr, to, cst;
}ed[maxm];
bool cmp(struct edge a, struct edge b){
return a.cst < b.cst;
}
bool _same( int a, int b ){
if( _find(a) != _find(b) )
return false;
return true;
}
int kruskal(){
int e;
int mmin = INF;
for(int i = 0; i < m; ++i){
e = 0;
init();
for(int j = i; j < m; j++){
if( !_same(ed[j].fr, ed[j].to) ){
e++;
if(e == n-1)
mmin = min(mmin, ed[j].cst-ed[i].cst);
_union(ed[j].fr, ed[j].to);
}
}
}
return mmin == INF ? -1 : mmin;
}
int main()
{
int a, b, c;
while( ~scanf("%d%d",&n, &m) && n ){
init();
memset(ed, 0, sizeof ed);
for(int i = 0; i < m; i++){
scanf("%d%d%d",&a, &b, &c);
ed[i] = {a,b,c};
}
sort(ed, ed+m, cmp);
printf("%d\n", kruskal());
}
return 0;
}