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

来源:互联网 发布:mafia 2 mac 编辑:程序博客网 时间:2024/05/18 17:04

下面用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;}


原创粉丝点击