这道题的目标是最大权值和最小权值的差最小,和最小生成树不太一样。
我们可以暴力枚举最小权值(放弃权值更小的边),然后求最小生成树。因为Kruscal算法按照权值顺序考虑各条边,所以一旦所有点连通,则可以计算出最大权值和最小权值的差并记录,然后continue。
Run Time: 0.079s
#define UVa "LT11-2.1395.cpp" //Slim Span
char fileIn[30] = UVa, fileOut[30] = UVa;
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<vector>
#include<iostream>
using namespace std;
//Global Variables. Reset upon Each Case!
const int maxn = 100+5, maxm = maxn*maxn;
int n, m, u[maxm], v[maxm], w[maxm], r[maxm];
int fa[maxn]; //union-find set.
/
int cmp(int a, int b) { return w[a] < w[b]; }
int find(int s) {
int t = s;
while(s != fa[s]) s = fa[s];
while(fa[t] != s) { //re-assign parent along the path
int tmp = fa[t];
fa[t] = s;
t = tmp;
}
return s;
}
int solve() {
int ans = -1;
for(int L = 0; L < m; L ++) {
for(int i = 1; i <= n; i ++) fa[i] = i;
for(int R = L; R < m; R ++) {
if(ans != -1 && ans <= w[r[R]] - w[r[L]]) break; //pruning
int e = r[R];
int x = find(u[e]), y = find(v[e]);
if(x != y) { //not in same connceted block, add it to connected block.
fa[x] = y;
for(int i = 2; i <= n; i ++) //check connected blocks
if(find(i) != find(i-1))
goto EXIT;
if(ans == -1) ans = w[r[R]] - w[r[L]];
else ans = min(ans, w[r[R]] - w[r[L]]);
break;
EXIT: continue;
}
}
}
return ans;
}
int main() {
while(scanf("%d%d", &n, &m) && n) {
for(int i = 0; i < m; i ++) {
scanf("%d%d%d", &u[i], &v[i], &w[i]);
r[i] = i;
}
sort(r, r+m, cmp);
cout<<solve()<<endl;
}
return 0;
}