https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=5015

设dp[cur][i][j]表示当前是第cur个顶点,自身状态是i(0或者1),爸爸的状态是j(0或者1)的时候的最多白色节点数。

0---白色

1---黑色

如果不合法,就是第cur号顶点不能染成白色,则为-1,注意到任意节点都可以染成黑色,所以dp[cur][1][0] = dp[cur][1][1] = 0

转移:

首先把叶子节点特判掉,因为叶子节点的状态很容易判断,并且只有k == 1的时候,才有dp[left][0][1] = 1

然后留给每一个爸爸的转移就是:

1、如果爸爸染黑色,则从  dp[son][1][1]和dp[son][0][1]娶个max过来即可。

2、比较麻烦的是爸爸染了白色。这样就相当于对于所有的儿子(儿子的状态已经全部算出来了),把k个染成黑色(使得爸爸合法),剩下的染成白色,使得白色节点数最大,

也就是给出一个结构体数组,有arr[i].a和arr[i].b表示这个节点染成白色,得到arr[i].a贡献,这个节点染成黑色,得到arr[i].b贡献。

设d[n][k]表示前n个物品,确定选了k个做黑色的最大贡献。二维费用背包转移即可。hack: 需要用到d[i][0]

所以d[0][0] = 0,而d[1][0] = arr[1].a    d[2][0] = arr[1].a + arr[2].a

这题写那个二维费用dp的时候坑队友了,没写出来,转移的时候没考虑d[i][0]

#include <bits/stdc++.h>
#include <algorithm>
#define inf (0x3f3f3f3f)
using namespace std;
typedef long long int LL;
const int maxn = 1e2 + ;
int dp[maxn][][];
char str[ + ];
struct Edge {
int u, v, tonext;
} e[maxn * ];
int first[maxn], num;
void addEdge(int u, int v) {
e[num].u = u, e[num].v = v, e[num].tonext = first[u];
first[u] = num++;
}
int son[maxn];
bool in[maxn];
int n, k; void show() {
for (int i = ; i <= n; ++i) {
printf("node %d: ", i);
for (int j = first[i]; ~j; j = e[j].tonext) {
printf("%d ", e[j].v);
}
printf("\n");
}
printf("***************\n");
}
vector<int> vc[maxn];
int d[maxn][];
struct Node {
int a, b;
Node(int _a, int _b) {
a = _a, b = _b;
}
Node() {}
} arr[maxn];
int getMax(struct Node arr[], int n, int k) {
if (k < ) return -inf;
if (k == ) {
int sum = ;
for (int i = ; i <= n; ++i) sum += arr[i].a;
return sum;
}
if (n < k) return -inf;
memset(d, -0x3f, sizeof d);
d[][] = ;
for (int i = ; i <= n; ++i) {
for (int j = k; j >= ; --j) {
if (d[i - ][j] >= ) d[i][j] = max(d[i][j], d[i - ][j] + arr[i].a);
if (j >= && d[i - ][j - ] >= ) d[i][j] = max(d[i][j], d[i - ][j - ] + arr[i].b);
}
}
return d[n][k];
}
void dfs(int cur) {
if (!son[cur]) return;
for (int i = first[cur]; ~i; i = e[i].tonext) {
int v = e[i].v;
vc[cur].push_back(v);
dfs(v);
dp[cur][][] += max(dp[v][][], dp[v][][]);
dp[cur][][] += max(dp[v][][], dp[v][][]); // 爸爸是黑色
}
int sel = , val = , to = ;
for (int i = ; i < vc[cur].size(); ++i) {
int v = vc[cur][i];
if (dp[v][][] >= ) {
arr[++to] = Node(dp[v][][], dp[v][][]);
} else {
sel++; //这些不能变成白色,也就是固定必须是黑色
val += dp[v][][]; //其贡献
}
}
dp[cur][][] = getMax(arr, to, k - - sel) + val;
dp[cur][][] = getMax(arr, to, k - sel) + val;
if (dp[cur][][] < ) dp[cur][][] = -;
else dp[cur][][]++;
if (dp[cur][][] < ) dp[cur][][] = -;
else dp[cur][][]++;
}
void work() {
num = ;
memset(in ,false, sizeof in);
memset(first, -, sizeof first);
memset(dp, -, sizeof dp);
memset(son, false, sizeof son);
scanf("%d%d", &n, &k);
for (int i = ; i <= maxn - ; ++i) vc[i].clear();
getchar();
for (int i = ; i <= n; ++i) {
gets(str + );
// printf("%s\n", str + 1);
int lenstr = strlen(str + );
for (int j = ; j <= lenstr;) {
if (str[j] >= '' && str[j] <= '') {
int fuck = str[j] - '';
++j;
while (j <= lenstr && str[j] >= '' && str[j] <= '') {
fuck = fuck * + str[j] - '';
++j;
}
if (fuck == ) break;
son[i]++;
addEdge(i, fuck);
in[fuck] = true;
} else j++;
}
}
int root = ;
for (int i = ; i <= n; ++i) {
if (!in[i]) {
root = i;
break;
}
}
// show();
if (n == ) {
if (k != ) {
printf("0\n");
return;
}
}
for (int i = ; i <= n; ++i) {
dp[i][][] = dp[i][][] = ;
}
if (k == ) {
printf("%d\n", n);
return;
}
if (k == ) {
for (int i = ; i <= n; ++i) {
if (!son[i]) {
dp[i][][] = ;
dp[i][][] = -;
dp[i][][] = ;
dp[i][][] = ;
}
}
}
dfs(root);
int ans = dp[root][][];
ans = max(ans, dp[root][][]);
ans = max(ans, dp[root][][]);
// ans = max(ans, dp[root][0][1]);
printf("%d\n", ans);
} int main() {
#ifdef local
freopen("data.txt", "r", stdin);
#endif
int t;
scanf("%d", &t);
while (t--) work();
return ;
}

Regionals 2014 >> Asia - Taichung 7003 - A Balance Game on Trees 树形DP + 二维费用背包的更多相关文章

  1. 2014 Super Training #9 E Destroy --树的直径+树形DP

    原题: ZOJ 3684 http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3684 题意: 给你一棵树,树的根是树的中心(到其 ...

  2. [The Preliminary Contest for ICPC Asia Nanjing 2019] A-The beautiful values of the palace(二维偏序+思维)

    >传送门< 前言 这题比赛的时候觉得能做,硬是怼了一个半小时,最后还是放弃了.开始想到用二维前缀和,结果$n\leq 10^{6}$时间和空间上都爆了,没有办法.赛后看题解用树状数组,一看 ...

  3. The Preliminary Contest for ICPC Asia Xuzhou 2019 J Random Access Iterator (树形DP)

    每次循环向下寻找孩子时,随机选取一个孩子,设dp[u]为从u出发,不能得出正确答案的概率,则从u出发,走一次的情况下不能得出正确答案的概率是 P = (dp[v1]+dp[v2]+dp[v3]+--d ...

  4. The Preliminary Contest for ICPC Asia Shenyang 2019 D. Fish eating fruit(树形dp)

    题意:求一棵树上所有路径和模3分别为0 1 2 的权值的和 思路:树形dp 增加一个记录儿子节点满足条件的个数的数组 不要放在一起dp不然答案跟新会有问题 #include <bits/stdc ...

  5. 2015 UESTC Winter Training #4【Regionals 2008 :: Asia - Tehran】

    2015 UESTC Winter Training #4 Regionals 2008 :: Asia - Tehran 比赛开始时电脑死活也连不上WIFI,导致花了近1个小时才解决_(:зゝ∠)_ ...

  6. C++ 洛谷 2014 选课 from_树形DP

    洛谷 2014 选课 没学树形DP的,看一下. 首先要学会多叉树转二叉树. 树有很多种,二叉树是一种人人喜欢的数据结构,简单而且规则.但一般来说,树形动规的题目很少出现二叉树,因此将多叉树转成二叉树就 ...

  7. hdu5071 2014 Asia AnShan Regional Contest B Chat

    模拟题: add的时候出现过的则不再添加 close的时候会影响到top rotate(Prior.Choose)的时候会影响到top /*============================== ...

  8. UVALive 7138 The Matrix Revolutions(Matrix-Tree + 高斯消元)(2014 Asia Shanghai Regional Contest)

    题目链接:https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&category=6 ...

  9. UVALive 7143 Room Assignment(组合数学+DP)(2014 Asia Shanghai Regional Contest)

    题目链接:https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&category=6 ...

随机推荐

  1. centos7添加环境变量

    # vim /etc/profile在最后,添加:export PATH="/usr/local/webserver/mysql/bin:$PATH" #添加的路径保存,退出,然后 ...

  2. HDOJ1671(字符串前缀匹配)

    #include<iostream> #include<cstdio> #include<string> #include<vector> #inclu ...

  3. 二叉搜索树的结构(30 分) PTA 模拟+字符串处理 二叉搜索树的节点插入和非递归遍历

    二叉搜索树的结构(30 分) 二叉搜索树或者是一棵空树,或者是具有下列性质的二叉树: 若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值:若它的右子树不空,则右子树上所有结点的值均大于它的根 ...

  4. 四种生成和解析XML文档的方法介绍

    解析XML的方法越来越多,但主流的方法也就四种,即:DOM.SAX.JDOM和DOM4J 1.DOM(Document Object Model) DOM是用与平台和语言无关的方式表示XML文档的官方 ...

  5. Selenium VS Webdriver

    Selenium 是 ThroughtWorks 一个强大的基于浏览器的开源自动化测试工具,它通常用来编写 Web 应用的自动化测试.随着 Selenium 团队发布 Selenium 2(又名 We ...

  6. <正则吃饺子> :关于gson使用的一点总结

    一.场景 在群里看到的信息:在使用 gson时候,报了个错 :java.lang.IllegalArgumentException:   declares multiple JSON fields n ...

  7. eclipse安装WTP部署WEB项目

    打开WTP官方安装指南,找到想要的下载站点 http://wiki.eclipse.org/WTP_FAQ#How_do_I_install_WTP.3F 我选择的是http://download.e ...

  8. 0010_while循环

    while 条件: 代码块 break:跳出循环语句 continue:跳出本次循环,进入下一次循环. __author__ = 'qq593' #!/usr/bin/env python #-*- ...

  9. 阿里巴巴Druid数据库连接池的使用

    准备: 创建一个基于SpringBoot的web项目 1 引入相关依赖 jpa.mysql.druid <?xml version="1.0" encoding=" ...

  10. 以后尽量不用cin、cout啦

    cout输出有问题(对于double,不同OJ处理的结果不一样),cin读入机制较scanf繁琐.慢!!!!!!!!