您的位置:首页 > 其它

2013 长沙Regional I题:LIKE vs CANDLE (树dp)

2013-11-24 22:12 337 查看
下面用0表示LIKE,1表示CANDLE。

设状态fw[u]表示以节点u为根的子树的 0-1 的最大值,用rv[u]表示以节点u为根的子树的 1-0 的最大值。则:

fw[u] = max(rv[u]-cost,sigma(fw[v]))

rv[u] = max(fw[u]-cost,sigma(rv[v]))

v 为u的子节点。而每个节点只考虑翻或者不翻,因此花费分别为X或Y。

cost虽然是花0的power,但是上面的两个转移都是 ‘-’ 号,这里我解释一下。

答案求的是0-1的最大值,而由于有翻转操作,因此最优解也可以从1-0的最大值来考虑,那么就是说,rv[u] 是 fw[u] 的替补项。而翻转操作,就是交换0和1,那么现在fw[u]中的0,就是原来rv[u]中的1,而cost要减在fw[u]中的[0]上,因此也就是要减在rv[u]的1上。从fw[u]-cost 转移到rv[u]同理。

/* Created Time: Sunday, November 24, 2013 PM09:27:20 CST */
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 55555;
int n,cx,cy;
int fw
,rv
; // 分别保存0,1最大的选项
struct edge {
int v,next;
}g[N<<1];
int head
,etot,w
,rev
,bel
;
void add_edge(int u,int v) {
g[etot].v = v; g[etot].next = head[u]; head[u] = etot ++;
}
void dfs(int u,int fa) {
fw[u] = rv[u] = 0;
if (bel[u]==0) {
fw[u] += w[u];
rv[u] -= w[u];
} else {
fw[u] -= w[u];
rv[u] += w[u];
}
for (int i = head[u]; i != -1; i = g[i].next) {
int v = g[i].v;
if (v==fa) continue;
dfs(v,u);
fw[u] += fw[v];
rv[u] += rv[v];
}
int cost = cx;
if (rev[u]) {
cost = cy;
swap(fw[u],rv[u]);
}
if (u) {
if (rv[u]-cost>fw[u]) fw[u] = rv[u]-cost;
if (fw[u]-cost>rv[u]) rv[u] = fw[u]-cost;
}
}
int main() {
while (~scanf("%d%d%d",&n,&cx,&cy)) {
memset(head,-1,sizeof(head));
etot = 0;
for (int i = 1; i <= n; i ++) {
int d;
scanf("%d%d%d%d",&w[i],&d,&rev[i],&bel[i]);
add_edge(d,i);
}
dfs(0,-1);
if (fw[0]<0) puts("HAHAHAOMG");
else printf("%d\n",fw[0]);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: