zoukankan      html  css  js  c++  java
  • bzoj3302

    树形dp

    很明显我们可以枚举一条边,然后求两边的重心,这样是暴力,我们用一些奇怪的方法来优化这个找重心的过程,我们先预处理出来每个点最大和第二的儿子,然后每次把断掉的子树的贡献减掉,每次找重心就是向最大或第二大的儿子走,如果最大的儿子被减掉后比第二大的儿子小或者这条边被剪掉了,那么就向第二大的儿子走,这样复杂度是h的

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int N = 5e4 + 5;
    int n;
    ll ans = 1e18;
    vector<int> G[N];
    int dep[N], a[N], fa[N], son[N], bro[N];
    ll sum[N], size[N];
    void dfs(int u, int last)
    {
        size[u] = a[u];
        fa[u] = last;
        for(int i = 0; i < G[u].size(); ++i)
        {
            int v = G[u][i];
            if(v == last) continue;
            dep[v] = dep[u] + 1;
            dfs(v, u);
            size[u] += size[v];
            sum[u] += sum[v] + size[v];
            if(!son[u] || size[v] > size[son[u]]) bro[u] = son[u], son[u] = v;
            else if(!bro[u] || size[v] > size[bro[u]]) bro[u] = v;
        }
    }
    void center(ll &ret, int ban, ll tot, int u, ll S)
    {
        ret = min(ret, S);
        int v = son[u];
        if(v == ban || size[bro[u]] > size[v]) v = bro[u];
        if(!v) return;
        center(ret, ban, tot, v, S + tot - 2 * size[v]);    
    }
    void solve(int u, int last) 
    {
        for(int i = 0; i < G[u].size(); ++i) 
        {
            int v = G[u][i];
            if(v == last) continue;
            for(int x = u; x; x = fa[x]) size[x] -= size[v];
            ll tmp1 = 1e16, tmp2 = 1e16;
            center(tmp1, v, size[1], 1, sum[1] - sum[v] - size[v] * dep[v]);
            center(tmp2, 1, size[v], v, sum[v]);
            ans = min(ans, tmp1 + tmp2);
            for(int x = u; x; x = fa[x]) size[x] += size[v];
            solve(v, u);
        }
    }
    int main()
    {
        scanf("%d", &n);
        for(int i = 1; i < n; ++i) 
        {
            int u, v;
            scanf("%d%d", &u, &v);
            G[u].push_back(v);
            G[v].push_back(u);
        }
        for(int i = 1; i <= n; ++i) scanf("%lld", &a[i]);
        if(n <= 2) 
        {
            puts("0");
            return 0;
        }
        dfs(1, 0);
        solve(1, 0);
        printf("%lld
    ", ans);
        return 0;
    }
    View Code
  • 相关阅读:
    mysql慢查询日志功能的使用
    回顾JavsScript对象的克隆
    JavaScript的几种继承方式
    再谈JavaScript中的闭包
    重温JavaScript预编译的四个步骤
    PHP常用设计模式
    编译 php-memcache 扩展时提示Cannot find autoconf
    CentOS 7 下编译安装lnmp之PHP篇详解
    CentOS 7 下编译安装lnmp之MySQL篇详解
    MySQL的转义符 ` 作用
  • 原文地址:https://www.cnblogs.com/19992147orz/p/7783120.html
Copyright © 2011-2022 走看看