• USACO17DEC Barn Painting


    给你一颗大小为n<=1e5的树,三种颜色,每个点涂一种颜色,相邻点不能同色。下面告诉你一些点已经被涂色,并
    且告诉你是哪一种颜色,问你涂完整棵树有多少种方法?mod 1e9+7。

    考虑树上dp,设(f_{u,i})表示以u为根的子树中,u被染成i这个颜色的方案数,于是考虑状态转移方程

    如果这个点被指定染色了,那么有

    [f_{u,c_u}=prod_{vin son(u)}sum_{i=1}^3 f_{v,i} (i e c_u) ]

    因为假如u选了一个颜色,那么它的每个儿子都只能有两种颜色可选,先用加法原理统计儿子可选的颜色,然后再用乘法原理统计这棵子树的答案

    然后可以得出未被指定颜色点的方程

    [egin{cases}f_{u,1}=prod_{vin son(u)} (f_{v,2}+f_{v,3})\f_{u,2}=prod_{vin son(u)} (f_{v,1}+f_{v,3})\f_{u,3}=prod_{vin son(u)} (f_{v,1}+f_{v,2}) end{cases}]

    这样就做完了QAQ

    Code

    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    #include <cstring>
    #include <vector>
    const int N = 1e5;
    const int p = 1e9 + 7;
    using namespace std;
    int n,k,c[N + 5],f[N + 5][4];
    vector <int> d[N + 5];
    void dfs(int u,int fa)
    {
        vector <int>::iterator it;
        int sum[4] = {1,1,1,1};
        for (it = d[u].begin();it != d[u].end();it++)
        {
            int v = (*it);
            if (v == fa)
                continue;
            dfs(v,u);
            if (c[u])
            {
                int s = 0;
                for (int i = 1;i <= 3;i++)
                    if (i != c[u])  
                        s = (s + f[v][i]) % p;
                sum[c[u]] = 1ll * sum[c[u]] * s % p;
            }
            else
                for (int i = 1;i <= 3;i++)
                {
                    int s = 0;
                    for (int j = 1;j <= 3;j++)
                        if (i != j)
                            s = (s + f[v][j]) % p;
                    sum[i] = 1ll * sum[i] * s % p;
                }
        }
        if (c[u])
            f[u][c[u]] = sum[c[u]];
        else
            for (int i = 1;i <= 3;i++)
                f[u][i] = sum[i];
    }
    int main()
    {
        scanf("%d%d",&n,&k);
        int u,v;
        for (int i = 1;i < n;i++)
        {
            scanf("%d%d",&u,&v);
            d[u].push_back(v);
            d[v].push_back(u);
        }
        for (int i = 1;i <= k;i++)
        {
            scanf("%d%d",&u,&v);
            c[u] = v;
        }
        dfs(1,0);
        cout<<((f[1][1] + f[1][2]) % p + f[1][3]) % p<<endl;  
        return 0;
    }
    
  • 相关阅读:
    dll得到主窗體的handle
    将应用程序11M内存占用,降至500K
    是否想为你的Windows加上一双眼睛,察看使用者在机器上所做的各种操作(例如建立、删除文件;改变文件或目录名字)呢?
    TreeView 之间节点拖动 /移动
    Delphi与C之间的类型对应表
    以ADO数据集相连的DBGrid按单一字段排序通用过程
    为Delphi程序添加事件和事件处理器
    DataSetToTreeView
    一个系统空闲时间函数
    调用chm
  • 原文地址:https://www.cnblogs.com/sdlang/p/13068297.html
Copyright © 2020-2023  润新知