zoukankan      html  css  js  c++  java
  • 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
    ");
            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;
    }
    View Code
  • 相关阅读:
    值得收藏的146条经典民间偏方[转]
    删除暴风文件夹内的stormliv.exe
    【转】VLAN技术浅谈
    [转载]双击.dsw文件时另开VC6.0,而不会关掉原来已打开的项目的解决办法(转载)
    JVM系列1:Java内存区域
    并发系列3:Lock锁以及核心类AQS
    并发系列1:并发基础知识
    JVM系列2:垃圾收集器与内存分配策略
    JVM系列3:类加载机制
    源码解析之AQS源码解析
  • 原文地址:https://www.cnblogs.com/liuweimingcprogram/p/6478560.html
Copyright © 2011-2022 走看看