kruskal算法利用并查集来处理联通分支,扫描后得到最小生成树的边。
本题要求最大边与最小边只差最小的最小生成树,感觉包含了尺取法的思想在里边。
但由于L++后,无法直接维护并查集,复杂度上仍为O(m*m)?
本题要求最大边与最小边只差最小的最小生成树,感觉包含了尺取法的思想在里边。
但由于L++后,无法直接维护并查集,复杂度上仍为O(m*m)?
#include <bits/stdc++.h>
using namespace std;
const int maxn = 105;
const int maxm = maxn*(maxn-1)/2;
const int inf = 1000000009;
struct Edge {
int u, v, w;
Edge(int u = 0, int v = 0, int w = 0): u(u), v(v), w(w) { }
}e[maxm];
int r[maxm];
int f[maxn];
int n, m;
int cnt;
void init() {
cnt = n - 1;
for(int i = 1; i <= n; ++i) f[i] = i;
}
bool cmp(int a, int b) { return e[a].w < e[b].w; }
int Find(int a) { return f[a] == a ? a : f[a] = Find(f[a]); }
bool unite(int a, int b) {
int fa = Find(a), fb = Find(b);
if(fa == fb) return false;
f[fa] = fb;
return true;
}
int main() {
//freopen("in.txt", "r", stdin);
//freopen("out.txt", "w", stdout);
while(scanf("%d%d", &n, &m) && n) {
int u, v, w;
for(int i = 0; i < m; ++i) {
scanf("%d%d%d", &u, &v, &w);
e[i] = {u, v, w};
r[i] = i;
}
//for(int i = 0; i < m; ++i) printf("r = %d\n", r[i]);
sort(r, r + m, cmp);
int ans = inf;
for(int i = 0; i < m; ++i) {
init();
int beg = e[r[i]].w;
for(int j = i; j < m; ++j) {
int cur = r[j];
if(unite(e[cur].u, e[cur].v)) {
if(--cnt == 0) {
ans = min(ans, e[cur].w - beg);
//printf("ans = %d\n", ans);
break;
}
}
}
//if(cnt) break;
}
if(ans == inf) ans = -1;
printf("%d\n", ans);
}
return 0;
}