zoukankan      html  css  js  c++  java
  • P3554 [POI2013]LUK-Triumphal arch

    P3554 POI2013LUK-Triumphal arch

    刚开始以为直接统计一个点最多的子树就好了。
    然后发现不是这样的,在涂上面的时候,有多余的可以直接涂到下面去,那么就直接二分+树DP就完了。
    也就是说我可以预判你要走哪些。
    (f_n) 是还需要多少次才能涂完一个点的全部子树。那么 (f_1 = 0) 就是满足要求的。
    (为什么能每一个点转移一次,是因为国王一次走一个点,他每走一个点,我就可以多涂 (mid) 次)
    式子是

    [f_n = max(0, sum - mid +d_n) ]

    (d_n) 是一个点的儿子数目。

    #include <algorithm>
    #include <iostream>
    #include <cstring>
    #include <cstdio>
    
    using namespace std;
    
    typedef long long ll;
    const ll MAXN = 1e6+10;
    
    struct edge {
        ll nt, to, v;
    } E[MAXN];
    
    ll N, M, head[MAXN], cnt = -1, ans, d[MAXN], f[MAXN], mid;
    
    void add(ll, ll);
    void pre(ll, ll);
    bool check();
    void dfs(ll, ll);
    
    int main() {
        memset(head, -1, sizeof(head));
        scanf("%lld", &N);
        for (ll x, y, i = 1; i < N; i++) {
            scanf("%lld%lld", &x, &y);
            add(x, y);
            add(y, x);
        }
        pre(1, 0);
        ll l = 0, r = N;
        while (l <= r) {
            mid = l + ((r - l) >> 1);
            if (check()) {
                ans = mid;
                r = mid - 1;
            } else {
                l = mid + 1;
            }
        }
        printf("%lld
    ", ans);
        return 0;
    }
    
    void pre(ll n, ll ff) {
        for (ll i = head[n]; ~i; i = E[i].nt) {
            ll v = E[i].to;
            if (v == ff) continue;
            else {
                pre(v, n);
                d[n]++;
            }
        }
    }
    
    bool check() {
        dfs(1, 0);
        return f[1] == 0;
    }
    
    void dfs(ll n, ll ff) {
        ll sum = 0;
        for (ll i = head[n]; ~i; i = E[i].nt) {
            ll v = E[i].to;
            if (v == ff) continue;
            else {
                dfs(v, n);
                sum += f[v];
            }
        }
        f[n] = max(0LL, sum - mid + d[n]);
    }
    
    void add(ll x, ll y) {
        cnt++;
        E[cnt].to = y;
        E[cnt].nt = head[x];
        head[x] = cnt;
    }
    
    Yukkuri si te yi te ne
  • 相关阅读:
    c语言数据处理!
    指针的概念
    return的用处
    用java写随机出题
    java 新手
    分支程序设计。
    不同车型 不同起步价不同费用的问题(switch语句)
    这两天做了很多随机函数的用法(下面是一个出题实验)。
    yum 命令讲解
    日常工作中一些常用命令
  • 原文地址:https://www.cnblogs.com/Gensokyo-Alice/p/13674355.html
Copyright © 2011-2022 走看看