zoukankan      html  css  js  c++  java
  • BZOJ 2654: tree(二分 最小生成树)

    Time Limit: 30 Sec  Memory Limit: 512 MB
    Submit: 2901  Solved: 1196
    [Submit][Status][Discuss]

    Description

    给你一个无向带权连通图,每条边是黑色或白色。让你求一棵最小权的恰好有need条白色边的生成树。
    题目保证有解。

    Input

    第一行V,E,need分别表示点数,边数和需要的白色边数。
    接下来E行,每行s,t,c,col表示这边的端点(点从0开始标号),边权,颜色(0白色1黑色)。

    Output

    一行表示所求生成树的边权和。
    V<=50000,E<=100000,所有数据边权为[1,100]中的正整数。

    Sample Input

    2 2 1
    0 1 1 1
    0 1 2 0

    Sample Output

    2

    HINT

    原数据出错,现已更新 by liutian,但未重测---2016.6.24

    Source

    对于图上的最小生成树

    如果我们得到的最小生成树上的白边小于$need$条,那么说明白边的权值整体偏大,

    那么我们考虑对所有的白边减去一个权值,这样最小生成树上的白边就会变多

    这个过程很显然具有单调性,于是可以二分减去的权值

    注意一个坑:当权值相同的时候优先选择白边

    #include<cstdio>
    #include<algorithm>
    using namespace std;
    const int MAXN = 1e6 + 10;
    inline int read() {
        char c = getchar(); int x = 0, f = 1; 
        while(c < '0' || c > '9') {if(c == '-') f = -1; c = getchar();}
        while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
        return x * f;
    }
    int N, M, need;
    struct Edge {
        int u, v, w, opt;
        bool operator <(const Edge &rhs) const {
            return w == rhs.w ? opt < rhs.opt : w < rhs.w;
        }
    }E[MAXN], e[MAXN];
    int Val = 0, fa[MAXN];
    int siz[MAXN];
    int find(int x) {
        return fa[x] == x ? fa[x] : fa[x] = find(fa[x]);
    }
    int unionn(int x, int y) {
        int fx = find(x), fy = find(y);
        if(siz[fx] < siz[fy]) swap(fx, fy);
        fa[fy] = fx;
    }
    bool check(int x) {
        Val = 0;
        for(int i = 1; i <= M; i++) {
            E[i] = e[i];
            if(e[i].opt == 0) E[i].w += x;
        }
        for(int i = 1; i <= N; i++) 
            fa[i] = i, siz[i] = 1;
        int tot = 0, white = 0;
        sort(E + 1, E + M + 1);
        for(int i = 1; i <= M; i++) {
            if(find(E[i].u) != find(E[i].v)) {
                unionn(E[i].u, E[i].v);
                Val += E[i].w; tot++;
                if(E[i].opt == 0) white++;
            }
            if(tot == N - 1) break;
        }
        return white >= need;
    }
    main() {
        #ifdef WIN32
        freopen("a.in", "r", stdin);
        #endif
        N = read(), M = read(), need = read();
        for(int i = 1; i <= M; i++) {
            int x = read() + 1, y = read() + 1, z = read(), opt = read();
            e[i] = (Edge){x, y, z, opt};
        }
        int l = -110, r = 110, ans = 0;
        while(l <= r) {
            int mid = l + r >> 1;
            if(check(mid)) ans = Val - mid * need, l = mid + 1;
            else r = mid - 1;    
        } 
        printf("%d", ans);
    }
  • 相关阅读:
    Version Control System, IntelliJ IDEA, Create a Git Repository for a Project and push to multiple remotes
    SWOT, Challenges to upgrade to MacOS Big Sur (Version 11.0.1)
    How to extract text from PDF(Image) files, OCR
    How to install NetSuite SuiteCloud plug-in to WebStorm
    How to use NetSuite SDF CLI, CLI for Node.js on Mac, suitecloud command
    How to use NetSuite SDF to download bundles/components
    How to run a NetSuite scheduled script at every month end
    js 如何让forEach可以break?
    How to setup oAuth 1.0 in NetSuite RESTlet API 如何在NetSuite中设置RESTlet API的oAuth认证
    关于带宽与网速和用户体验
  • 原文地址:https://www.cnblogs.com/zwfymqz/p/9060241.html
Copyright © 2011-2022 走看看