POJ 3522 Slim Span 暴力枚举 + 并查集

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\n");
        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\n", 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;
}
View Code

 

posted on 2017-02-28 13:54  stupid_one  阅读(139)  评论(0编辑  收藏  举报

导航