• CQOI2009 叶子的染色


    题目链接

    Solution

    结论一:根节点的选择不影响答案。

    证明:(因为大佬的证明都看不懂,这里给出一个很菜的证明)

    假设 1,2 是两个相邻的节点,现在以 1 为根。两节点的子树如图 [1] 所示。现在子树 A 依赖 1 的染色,子树 B 依赖 2 的染色。

    现在考虑将两个节点交换(2 为根,1 为 2 的子树),如图 [2] 所示。两者的依赖关系不变。

    那么如果节点 1 未染色呢?手推一下答案也是一样的。

    Code

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #define LL long long
    using namespace std;
    
    const int N = 23333;
    const LL INF = 1e16;
    struct edge { LL nxt, to; } e[N * 66];
    LL n, m, root, cnt = 0, c[N], du[N], head[N], f[N][2];
    
    void add(LL x, LL y)
    {
        e[++cnt] = (edge) { head[x], y };
        head[x] = cnt;
    }
    
    void dfs(LL x, LL fa)
    {
        if(x <= n) f[x][c[x] ^ 1] = INF;
        for(int i = head[x]; i; i = e[i].nxt)
        {
            LL v = e[i].to;
            if(v == fa) continue;
            dfs(v, x);
            f[x][0] += min(f[v][0] - 1, f[v][1]);
            f[x][1] += min(f[v][1] - 1, f[v][0]);
        }
    }
    
    int main()
    {
        scanf("%lld%lld", &m, &n);
        memset(f, 0, sizeof(f));
        memset(du, 0, sizeof(du));
        memset(head, 0, sizeof(head));
        for(int i = 1; i <= n; i++) scanf("%lld", &c[i]);
        for(LL u, v, i = 1; i < m; i++)
        {
            scanf("%lld%lld", &u, &v);
            add(u, v), add(v, u);
            du[u]++, du[v]++;
        }
        for(int i = 1; i <= m; i++) f[i][0] = f[i][1] = 1;
        for(int i = n + 1; i <= m; i++)
            if(du[i] > 1) { root = i; break; }
        dfs(root, 0);
        printf("%lld", min(f[root][0], f[root][1]));
        return 0;
    }
    
  • 相关阅读:
    管理者的主要任务是什么?
    管理者的最基本职责是什么?
    管理者的两大职责:“管事”和“理人”
    最近的思考
    刨根问底Objective-C Runtime
    Objective-C 中的类和对象
    ios动态添加属性的几种方法
    多态 oc c++ 与oc category
    利用Objective-C运行时hook函数的三种方法
    Hook技术
  • 原文地址:https://www.cnblogs.com/Andy-park/p/13680235.html
Copyright © 2020-2023  润新知