Virus Tree 2(树形DP)

题意

给定一个N个节点的树以及K种颜色。对于树上的每个节点,你可以选择其中一种颜色给它染色,但是必须满足如下条件:

任意两个距离不超过2的节点,那么的颜色不能相同。

问:有多少种染色的方案。

题目链接:https://atcoder.jp/contests/abc133/tasks/abc133_e

数据范围

1N,K105

思路

从上到下求每个节点的染色方案数,最终所有节点的方案数相乘即为答案。

根节点的染色数是k

对于每个节点,对其产生影响的节点是:父亲的父亲节点、父亲节点、已经枚举过的兄弟节点。

因此,我们分类讨论,

如果是第一个枚举到的子节点,那么其染色数是k1,如果父亲的父亲节点存在,那么为k2

如果不是第一个枚举到的子节点,那么其染色数为上一个子节点的染色数1

代码

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;

typedef long long ll;

const int N = 100010, M = 2 * N, mod = 1e9 + 7;

int n;
ll k;
int h[N], e[M], ne[M], idx;
ll f[N];

void add(int a, int b)
{
    e[idx] = b, ne[idx] = h[a], h[a] = idx ++;
}

void dfs(int u, int fa)
{
    ll last = 0;
    for(int i = h[u]; ~i; i = ne[i]) {
        int j = e[i];
        if(j == fa) continue;
        if(!last) {
            if(fa == -1) f[j] = k - 1;
            else f[j] = k - 2;
        }
        else f[j] = last - 1;
        last = f[j];
        dfs(j, u);
    }
}

int main()
{
    scanf("%d%lld", &n, &k);
    memset(h, -1, sizeof h);
    for(int i = 1; i < n; i ++) {
        int a, b;
        scanf("%d%d", &a, &b);
        add(a, b), add(b, a);
    }
    f[1] = k;
    dfs(1, -1);
    ll ans = 1;
    for(int i = 1; i <= n; i ++) ans = ans * f[i] % mod;
    printf("%lld\n", ans);
    return 0;
}
posted @   pbc的成长之路  阅读(41)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示