• cf444E. DZY Loves Planting(并查集)


    题意

    题目链接

    Sol

    神仙题啊Orzzzzzz

    考场上的时候直接把树扔了对着式子想,想1h都没得到啥有用的结论。

    然后cf正解居然是网络流??出给NOIP模拟赛T1???¥%……&((……%&((

    说一下非网络流解法吧。

    首先题目中给出的(g(i, p_i))我们可以认为是对于每个节点(i),分配一个节点(p_i),同时还有数量(x_i)的限制

    同时题目中要求的是最小值最大,不难想到二分答案。但其实只要把边从小到大排序,依次考虑每条边能否成为答案就行了

    用并查集维护节点之间的联通性,对于一条边来说,如果这条边可以成为答案,那么对于当前已经合并的每个点,我们都需要给它分配一个未被合并的点(注意这里边权是已经排好序的)

    维护(siz[x])表示(x)节点的连通块的大小,(sum = sum_{i = 1}^n x_i), (f[x])表示已经合并的节点的(x_i)之和(也就是不能使用的点)

    那么一条边可以被合并的条件为(siz[x] <= sum - f[x])

    #include<bits/stdc++.h>
    using namespace std;
    const int MAXN = 1e5 + 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, fa[MAXN], x[MAXN], siz[MAXN], sum;
    struct Edge {
        int u, v, w;
        bool operator < (const Edge &rhs) const {
            return w < rhs.w;
        }
    }E[MAXN];
    int find(int x) {
        return fa[x] == x ? x : fa[x] = find(fa[x]);
    }
    int main() {
        N = read();
        for(int i = 1; i <= N; i++) fa[i] = i, siz[i] = 1;
        for(int i = 1; i <= N - 1; i++) E[i].u = read(), E[i].v = read(), E[i].w = read();
        sort(E + 1, E + N);
        for(int i = 1; i <= N; i++) x[i] = read(), sum += x[i];
        for(int i = 1; i <= N - 1; i++) {
            int fx = find(E[i].u), fy = find(E[i].v);
            if(fx == fy) continue;
            fa[fy] = fx; siz[fx] += siz[fy]; x[fx] += x[fy];
            if(siz[fx] > sum - x[fx]) {printf("%d
    ", E[i].w); return 0;}
        }
        printf("%d
    ", E[N - 1].w);
        return 0;
    }
    
  • 相关阅读:
    笨办法06字符串(string)和文本
    react学习之路-配制antd-mobile
    react.js学习之路六
    bug
    react.js学习之路五
    react.js学习之路四
    react.js学习之路三
    react.js学习之路二
    react.js学习之路一
    MVC,MVP 和 MVVM 的区别之处
  • 原文地址:https://www.cnblogs.com/zwfymqz/p/9865807.html
Copyright © 2020-2023  润新知