• Codeforces 581F Zublicanes and Mumocrates 树形dp


    Zublicanes and Mumocrates

    dp[ i ][ j ][ k ] 表示 以 i 为根的子树, 占领 i 的 是 j 并且第一个人占了 i 子树的 k 个叶子节点的最小值。

    然后随便d 1 d 就好了。

    #include<bits/stdc++.h>
    #define LL long long
    #define LD long double
    #define ull unsigned long long
    #define fi first
    #define se second
    #define mk make_pair
    #define PLL pair<LL, LL>
    #define PLI pair<LL, int>
    #define PII pair<int, int>
    #define SZ(x) ((int)x.size())
    #define ALL(x) (x).begin(), (x).end()
    #define fio ios::sync_with_stdio(false); cin.tie(0);
    
    using namespace std;
    
    const int N = 5000 + 7;
    const int inf = 0x3f3f3f3f;
    const LL INF = 0x3f3f3f3f3f3f3f3f;
    const int mod = 1e9 + 7;
    const double eps = 1e-8;
    const double PI = acos(-1);
    
    template<class T, class S> inline void add(T& a, S b) {a += b; if(a >= mod) a -= mod;}
    template<class T, class S> inline void sub(T& a, S b) {a -= b; if(a < 0) a += mod;}
    template<class T, class S> inline bool chkmax(T& a, S b) {return a < b ? a = b, true : false;}
    template<class T, class S> inline bool chkmin(T& a, S b) {return a > b ? a = b, true : false;}
    
    int n, leaf;
    int dp[N][2][N];
    int tmp[2][N];
    int sum[N];
    bool isleaf[N];
    vector<int> G[N];
    
    void dfs(int u, int fa) {
        if(isleaf[u]) {
            dp[u][0][1] = dp[u][1][0] = 0;
            sum[u] = 1;
            return;
        }
        dp[u][1][0] = dp[u][0][0] = 0;
        for(auto& v : G[u]) {
            if(v == fa) continue;
            dfs(v, u);
            memset(tmp, inf, sizeof(tmp));
            for(int i = 0; i < 2; i++) {
                for(int j = 0; j < 2; j++) {
                    for(int c1 = 0; c1 <= sum[u]; c1++) {
                        for(int c2 = 0; c2 <= sum[v]; c2++) {
                            chkmin(tmp[i][c1 + c2], dp[u][i][c1] + dp[v][j][c2] + (i != j));
                        }
                    }
                }
            }
            sum[u] += sum[v];
            memcpy(dp[u], tmp, sizeof(dp[u]));
        }
    }
    
    int main() {
        memset(dp, inf, sizeof(dp));
        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);
        }
        if(n == 2) return puts("1"), 0;
        int root = -1;
        for(int i = 1; i <= n; i++) {
            if(SZ(G[i]) != 1) root = i;
            else leaf++, isleaf[i] = true;
        }
        dfs(root, 0);
        printf("%d
    ", min(dp[root][0][leaf >> 1], dp[root][1][leaf >> 1]));
        return 0;
    }
    
    /*
    */
  • 相关阅读:
    高中教材记录
    帮我解决逆序问题的网友:@18数院啦啦啦。恶人:16 师大 很菜 刘琳(2196879114) 2:32:49 PM
    丘维声的视频地址,全部课堂
    理工医疗报销电话
    可汗化学和二项式定理的地址
    二次函数问题
    *0000181894BD*---------北大医院条形码
    三月里的小雨
    语文容易读错的字
    mongodb部署
  • 原文地址:https://www.cnblogs.com/CJLHY/p/10789340.html
Copyright © 2020-2023  润新知