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

下面用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[N],rv[N]; // 分别保存0,1最大的选项
struct edge {
    int v,next;
}g[N<<1];
int head[N],etot,w[N],rev[N],bel[N];
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;
}


  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值