http://poj.org/problem?id=3522
一开始做这个题的时候,以为复杂度最多是O(m)左右,然后一直不会。最后居然用了一个近似O(m^2)的62ms过了。
一开始想到排序,然后扫一个长度n - 1区间,要快速判定这个区间能否构成MST,一直都想不到优秀的算法,然后干脆暴力了。
两种方法,1、dfs,删边容易,标记一下就好,但是这是不行的,删边确实容易,但是dfs的时候多次访问无用的边,所以TLE了。
2、并查集,这个复杂度是O(n)的,能AC,但是我的思路还是有一点bug,就是它不一定是在连续的n - 1个的区间上的。
7 7
1 2 1
2 3 2
3 4 3
4 5 4
5 6 5
4 6 5
5 7 6
0 0
所以,我只枚举起点,然后在后面找一颗MST算了,复杂度好想是O(m^2)啊,。。。。。

#include <cstdio> #include <cstdlib> #include <cstring> #include <cmath> #include <algorithm> #include <assert.h> #define IOS ios::sync_with_stdio(false) using namespace std; #define inf (0x3f3f3f3f) typedef long long int LL; #include <iostream> #include <sstream> #include <vector> #include <set> #include <map> #include <queue> #include <string> #include <bitset> int n, m; const int maxn = 100 + 20; struct Data { int u, v, w, id; bool operator < (const struct Data & rhs) const { return w < rhs.w; } }a[10000 * 2]; int fa[maxn]; int tofind(int u) { if (u == fa[u]) return u; else return fa[u] = tofind(fa[u]); } bool tomerge(int x, int y) { x = tofind(x); y = tofind(y); if (x == y) return false; fa[y] = x; return true; } void init() { for (int i = 1; i <= n; ++i) fa[i] = i; } bool check() { int has = 0; for (int i = 1; i <= n; ++i) { has += tofind(i) == i; if (has == 2) return false; } return true; } void work() { for (int i = 1; i <= m; ++i) { scanf("%d%d%d", &a[i].u, &a[i].v, &a[i].w); a[i].id = i; } if (m < n - 1) { printf("-1 "); return; } sort(a + 1, a + 1 + m); int ans = inf; for (int i = 1; i <= m; ++i) { int has = 0; if (i + (n - 1) - 1 > m) break; init(); bool flag = true; int mx; for (int j = i; j <= m && has != n - 1; ++j) { mx = a[j].w; if (a[j].w - a[i].w > ans) { flag = false; break; } if (tomerge(a[j].u, a[j].v)) { has++; } } if (flag && check()) { ans = min(ans, mx - a[i].w); } } if (ans == inf) ans = -1; printf("%d ", ans); } int main() { #ifdef local freopen("data.txt", "r", stdin); // freopen("data.txt", "w", stdout); #endif while (scanf("%d%d", &n, &m) > 0 && n + m) work(); return 0; }