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. 【Selenium07篇】python+selenium实现Web自动化:PO模型,PageObject模式!

    一.前言 最近问我自动化的人确实有点多,个人突发奇想:想从0开始讲解python+selenium实现Web自动化测试,请关注博客持续更新! 这是python+selenium实现Web自动化第七篇博 ...

  2. hibernate.current_session_context_class 比较权威的解释

    hibernate.current_session_context_class 博客分类: hibernate HibernateSpring多线程配置管理thread  遇到过的问题: 情景1: 在 ...

  3. 【Tool】使用IDEA创建简单的Java项目

    IDEA创建简单的Java项目 打开IDEA进入首页面,点击 Create New Project 点选第一项就是了,SDK就是我们的JDK,,这里我已经装好了JDK和JDK的环境变量 IDEA就能自 ...

  4. 使用d3.js的时候,如何用zoom translate scale限制拖拽范围

    红色代表需要改写的代码 1.添加定义图像大小和容器的大小及坐标 d3.behavior.zoom = function () { var moveCanvas={ width: , height: , ...

  5. sublime text3添加并修改编译系统

    版权声明:本文为CSDN博主「肥宅_Sean」的原创文章,遵循 CC 4.0 BY-SA 版权协议,原文链接 方法工具 -> 编译系统 -> 新建编译系统 按ctrl+s保存.(注意,这里 ...

  6. Django文档阅读-Day1

    Django文档阅读-Day1 Django at a glance Design your model from djano.db import models #数据库操作API位置 class R ...

  7. 20200107——记spring的DataSource

    spring项目中总要跟数据库打交道,其中怎么连接数据库的方法都有很多,大概分为3类: 1) 通过JNDI获取应用服务器(如JBOSS, Tomcat) 的数据源 2)  Spring容器中直接配置数 ...

  8. MergeSort归并排序和利用归并排序计算出数组中的逆序对

    首先先上LeetCode今天的每日一题(面试题51. 数组中的逆序对): 在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对.输入一个数组,求出这个数组中的逆序对的总数. ...

  9. CountDownLatch/CyclicBarrier/Semaphore

    CountDownLatch 概念 让一些线程阻塞直到另一些线程完成一系列操作才被唤醒 CountDownLatch主要有两个方法,当一个或多个线程调用await方法时,调用线程就会被阻塞.其它线程调 ...

  10. js拼接php拼接

    当我们用到ajax的时候,局部替换的时候,我们可以在前台拼接,后台拼接,这个取决于你是前端后端这样拼接判断比较好, 判断不拼接,判断的值进行拼接  然后在html  替换 $.each 前台循环    ...