C. Helga Hufflepuff's Cup

这个题目我感觉挺难的,想了好久也写了很久,还是没有写出来。

dp[i][j][k] 代表以 i 为根的子树中共选择了 j 个特殊颜色,且当前节点 i 的状态为 k 的染色方案数。

  1. k=0 ,代表当前节点 i 的颜色值小于 K 。
  2. k=1,代表当前节点 i 的颜色值等于 K 。
  3. k=2,代表当前节点 i 的颜色值大于 K 。

但是这个dfs过程的处理我觉得很复杂。

我们需要一个数组来进行临时的存储。

tmp[i][k] 表示选了 i 个  状态为 j 的方案数。

先枚举这个点已经用了 i 个,然后枚举这个子节点可以加上 j 个

tmp[j + h][0] += dp[u][j][0] * (dp[v][h][0] + dp[v][h][1] + dp[v][h][2]) % mod;
tmp[j + h][0] %= mod;
tmp[j + h][1] += dp[u][j][1] * dp[v][h][0] % mod;
tmp[j + h][1] %= mod;
tmp[j + h][2] += dp[u][j][2] * (dp[v][h][0] + dp[v][h][2]) % mod;
tmp[j + h][2] %= mod;

然后每次再赋值回去,注意这个tmp的定义,tmp[i,j]是k有 i 个,状态为 j 的方案。

这个地方我觉得挺难想的,我是没有想到。

这个是对于每一个节点u,我们枚举它的子树,一开始这个dp[u] 的初始化要注意,

我们先考虑如果子树没有k,这个状态是怎么样的,因为只有这个状态我们是可以定下来的,如果有k,这种状态必须通过转移得来。

然后再枚举子树k的个数,再去更新这个节点u。

这里用了一点点的乘法原理,挺厉害的,我一开始想的是,枚举这个u的所有可能的k的数量,然后再去用背包,这个好像有点不对。

因为我们不是取最大的那个,而是取求组合数,应该枚举每一种可能,然后相乘,也有可能是我想的不太对。

#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#include <queue>
#include <vector>
#include <iostream>
#include <string>
#define inf 0x3f3f3f3f
#define inf64 0x3f3f3f3f3f3f3f3f
using namespace std;
const int maxn = 2e5 + ;
const int mod = 1e9 + ;
typedef long long ll;
struct node {
int v, nxt;
node(int v = , int nxt = ) :v(v), nxt(nxt) {}
}ex[maxn];
int head[maxn], cnt = ;
int n, m, k, x;
void init()
{
memset(head, -, sizeof(head));
cnt = ;
}
void add(int u,int v)
{
ex[cnt] = node(v, head[u]);
head[u] = cnt++;
ex[cnt] = node(u, head[v]);
head[v] = cnt++;
}
int num[maxn];
ll tmp[][];
ll dp[maxn][][];//注意这个dp的定义,dp[i,j,x]表示到i这个节点,子树用k的数量为j,x==0 表示这个节点小于k,1代表等于k,2代表大于k
void dfs(int u,int pre)
{
dp[u][][] = k - ;
dp[u][][] = ;
dp[u][][] = m - k;
num[u] = ;
for (int i = head[u]; i != -; i = ex[i].nxt) {
int v = ex[i].v;
if (v == pre) continue;
dfs(v, u);
memset(tmp, , sizeof(tmp));
for (int j = ; j <= num[u]; j++) {
for (int h = ; h <= num[v]; h++) {
if (j + h > x) continue;
tmp[j + h][] += dp[u][j][] * (dp[v][h][] + dp[v][h][] + dp[v][h][]) % mod;
tmp[j + h][] %= mod;
tmp[j + h][] += dp[u][j][] * dp[v][h][] % mod;
tmp[j + h][] %= mod;
tmp[j + h][] += dp[u][j][] * (dp[v][h][] + dp[v][h][]) % mod;
tmp[j + h][] %= mod;
}
}
num[u] = min(x, num[u] + num[v]);
for (int j = ; j <= num[u]; j++) {
for (int h = ; h < ; h++) {
dp[u][j][h] = tmp[j][h];
}
}
}
} int main()
{
init();
scanf("%d%d", &n, &m);
for(int i=;i<=n-;i++)
{
int u, v;
scanf("%d%d", &u, &v);
add(u, v);
}
ll ans = ;
scanf("%d%d", &k, &x);
dfs(, -);
for (int i = ; i <= x; i++) {
for (int j = ; j < ; j++) {
ans = (ans + dp[][i][j]) % mod;
}
}
printf("%lld\n", ans);
return ;
}

C. Helga Hufflepuff's Cup 树形dp 难的更多相关文章

  1. Codeforces 855C - Helga Hufflepuff's Cup

    855C - Helga Hufflepuff's Cup 题意 要求构建一棵树,树上至多可以存在 \(x\) 个权值为 \(k\) 的重要点,且与重要点连边的点的权值必须小于 \(k\),问有多少种 ...

  2. Helga Hufflepuff's Cup CodeForces - 855C

    Helga Hufflepuff's Cup CodeForces - 855C 题意:给一棵n个节点的树,要给每一个节点一个附加值,附加值可以为1-m中的一个整数.要求只能有最多x个节点有附加值k. ...

  3. Codeforces 855C. Helga Hufflepuff's Cup----树形DP

    z最近在学习树形DP...好难啊. 在cf上找到了一题c题当模版马克一下. 题目不贴了..>>http://codeforces.com/problemset/problem/855/C& ...

  4. codeforces:Helga Hufflepuff's Cup

    题目大意:有一个包含n个顶点的无向无环连通图G,图中每个顶点都允许有一个值type,type的范围是1~m.有一个特殊值k,若一个顶点被赋值为k,则所有与之相邻的顶点只能被赋小于k的值.最多有x个顶点 ...

  5. 【DP】【CF855C】 Helga Hufflepuff's Cup

    Description 给你一个树,可以染 \(m\) 个颜色,定义一个特殊颜色 \(k\) , 要求保证整棵树上特殊颜色的个数不超过 \(x\) 个.同时,如果一个节点是特殊颜色,那么它的相邻节点的 ...

  6. 855C Helga Hufflepuff's Cup

    传送门 题目大意 给你一棵树,可以染m种颜色,现定义一种特殊的颜色K,一棵树上最多能有x个特殊颜色.如果一个节点为特殊颜色,那么他相邻的节点的值只能选比K小的颜色,问一共有多少种染色方案. 分析 不难 ...

  7. 【codeforces Manthan, Codefest 17 C】Helga Hufflepuff's Cup

    [链接]h在这里写链接 [题意]     k是最高级别的分数,最高界别的分数最多只能有x个.     1<=k<=m;     和k相邻的点的分数只能小于k;     n个点的树,问你每个 ...

  8. 8VC Venture Cup 2016 - Final Round (Div. 1 Edition) E - Preorder Test 树形dp

    E - Preorder Test 思路:想到二分答案了之后就不难啦, 对于每个答案用树形dp取check, 如果二分的值是val, dp[ i ]表示 i 这棵子树答案不低于val的可以访问的 最多 ...

  9. VK Cup 2012 Round 1 D. Distance in Tree (树形dp)

    题目:http://codeforces.com/problemset/problem/161/D 题意:给你一棵树,问你两点之间的距离正好等于k的有多少个 思路:这个题目的内存限制首先大一倍,他有5 ...

随机推荐

  1. 拓扑排序入门详解&&Educational Codeforces Round 72 (Rated for Div. 2)-----D

    https://codeforces.com/contest/1217 D:给定一个有向图,给图染色,使图中的环不只由一种颜色构成,输出每一条边的颜色 不成环的边全部用1染色 ps:最后输出需要注意, ...

  2. Docker 清理命令 删除所有的镜像和容器

    杀死所有正在运行的容器 docker kill $(docker ps -a -q) 删除所有已经停止的容器 docker rm $(docker ps -a -q) 删除所有未打 dangling ...

  3. 【公益线上自习室】不连麦,无微信群,无qq群

    马上就要到5月了,从刚开始的放纵已经逐渐变得慌乱. 疫情还没有完全过去,居家学习.工作是最好的选择. 但是,问题是,在家太舒服了,一点也不想学习. 一开始“哈哈哈哈哈哈哈哈”朋友了,现在已经开始“唉… ...

  4. For循环详解

    for语句 学过c语言都对循环结构不陌生,尤其是for循环,他是C语言中最有特色的循环语句,使用最为灵活. 形式 结构:for(表达式1:表达式2:表达式3){循环体结构} 每部分的作用 表达式1:一 ...

  5. Thinking in Java,Fourth Edition(Java 编程思想,第四版)学习笔记(一)之Introduction

    Learn Java I found out that I and other speakers tended to give the typical audience too many topics ...

  6. nmon 的下一代工具 njmon

    njmon njmon = nmon + JSON format + real-time push to a stats database + instant graphing of "al ...

  7. 安装python3.8和python2.7

    在同一台电脑上同时安装Python2和Python3 目前Python的两个版本Python2和Python3同时存在,且这两个版本同时在更新与维护. 到底是选择Python2还是选择Python3, ...

  8. CTF中的命令执行绕过

    本位原创作者:Smity 在介绍命令注入之前,有一点需要注意:命令注入与远程代码执行不同.他们的区别在于,远程代码执行实际上是调用服务器网站代码进行执行,而命令注入则是调用操作系统命令进行执行. 作为 ...

  9. deepin右键发送博客

    1. 概述 deepin系统上没有像样的笔记软件.为知笔记未提供deb打包的软件,很遗憾.商店提供的软件,界面停留在上个世纪了. 这个时候如果想通过笔记来分享到博客是一件非常困难的事情. 本篇博客就是 ...

  10. [PHP][thinkphp5] 学习一:增删改查

    <?php namespace app\index\controller; use think\Controller; use think\Db; class Test extends Cont ...