HDU 4799 LIKE vs CANDLE 树形dp

LIKE vs CANDLE

Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 327680/327680 K (Java/Others)
Total Submission(s): 242    Accepted Submission(s): 53


Problem Description
A microblog caused a war recently - There's the war between LIKE and CANDLE.


As you see, there are N accounts are trying to show their support of LIKE or CANDLE. The way they show the support is forwarding a microblog, which means you choose someone's microblog and repost it with some comment. A valid support microblog is forwarding the original account's microblog or a other valid support microblog. We can assume that all accounts will forward the microblog only once. Also, it is impossible for a microblog forwarding a microblog that posts after it. When the activity ends, someone will use a software to check these accounts and calculate a Power Point for LIKE and CANDLE. Specifically, each account will have a value based on some algorithm (you need not to care). The value will be added to LIKE if the account is voting LIKE, vice versa. So easy, isn't it?
Edward is a programmer and he supports LIKE. He found a bug in the software that used in the activity - He can spend X Power Point of LIKE to flip an account. When an account is flipped, it will be seen as it votes the other side. For example, if Alice votes LIKE and then it is flipped, the software will add the value to CANDLE. Of course, an account can be flipped for several times - If Alice is flipped again, it votes for LIKE again. And if we called the account the flipped account (Notice it's only a concept indicates the account has been flipped and not an attribute of an account), all accounts which forwarding the flipped account's microblog will also be flipped. Soon, Edward found that someone uses this bug before! Some accounts have been flipped already. He can't spend X Power Point to flip them anymore; instead, he need spend Y Power Point to flip an account which has been flipped directly by someone. For the glory of the LIKE, please help Edward to flip accounts so that the Power Point of LIKE can be larger than CANDLE as much as possible.
You can spend Power Point as much as you like, no matter the total Power Point of LIKE is negative or not.
 

Input
The input contains no more than 20 test cases. Notice there's no empty line between each test case.
For each test case, first line has three integers N (1 ≤ N ≤ 50000) - the number of the accounts, X (0 ≤ X ≤ 1000) and Y (0 ≤ Y ≤ 1000) - as the problem description. The account is numbered from 1 to N and 0 represent the original account.
Following N lines, the i th line means the i th account. Each line has four integers: V (0 ≤ V ≤ 1000) - the value of the i th account, F (0 ≤ F ≤ N) - which account did the i th account's forwarding account come from (0 th microblog is original account's microblog), S (0 ≤ S ≤ 1) - the status of flipped (0 means no changed, 1 means changed) and P (0 ≤ P ≤ 1) - the side the account supports without flipped (0 means LIKE, 1 means CANDLE).
The original microblog's account can't be flipped, and it hasn't the value and the support side.
 

Output
For each test case print an integer, represents the maximum result of the value of LIKE minus the value of CANDLE. If the value of CANDLE is larger than the LIKE, then just output "HAHAHAOMG" (without quote).
 

Sample Input
  
  
4 3 2 5 0 0 0 3 1 0 1 4 2 1 0 1 2 0 0
 

Sample Output
  
  
8
 

Source


百度能查到....说的也比较清晰的


代码:

#include <iostream>
#include <vector>
#include <algorithm>
#include <string.h>
#include <cstring>
#include <time.h>
#include <stdio.h>
#include <cmath>
#include <math.h>
#define rep(i,a,b) for(int i=(a);i<(b);++i)
#define rrep(i,b,a) for(int i = (b); i >= (a); --i)
#define clr(a,x) memset(a,(x),sizeof(a))
#define LL long long
#define eps 1e-10
using namespace std;
const int maxn = 50000 + 5;

struct Node
{
    int v;
    Node * next;
}*first[maxn], edges[maxn*2];
int ptr;

void add(int u,int v)
{
    edges[++ptr].v = v;
    edges[ptr].next = first[u];
    first[u] = &edges[ptr];
}

int value[maxn],cost[maxn];
int flip[maxn], state[maxn];
int fa[maxn];
int n, x, y;
int q[maxn];
void bfs()
{
    int l = 0, r = 0;
    q[r++] = 0;
    while (l < r) {
        int u = q[l++];
        if (flip[u]) state[u] ^= 1;
        for(Node * p = first[u]; p ; p = p->next) {
            int v = p->v;
            flip[v] ^= flip[u];
            q[r++] = v;
        }
    }
    rep(i,1,n+1) {
        if (state[i] == 1)
        value[i] = -value[i];
//        printf("%d : %d\n",i,state[i]);
    }
}

void input()
{
    clr(first,0); ptr = 0;
    rep(i,1,n+1) {
        scanf("%d",value+i);
        scanf("%d",fa+i);
        add(fa[i],i);
        scanf("%d",flip+i);
        cost[i] = flip[i] ? y : x;
        scanf("%d",&state[i]);
    }
    bfs();
}

int dp[maxn][2][2];
void solve()
{
    clr(dp,0);
    value[0] = cost[0] = 0;
    rrep(i,n,0) {
        int u = q[i];
        for(Node * p = first[u]; p ; p = p->next) {
            int v = p->v;
            dp[u][0][0] += max(dp[v][1][0],dp[v][0][0]);
            dp[u][0][1] += max(dp[v][1][1],dp[v][0][1]);
            dp[u][1][0] += max(dp[v][1][1],dp[v][0][1]);
            dp[u][1][1] += max(dp[v][1][0],dp[v][0][0]);
        }
        dp[u][0][0] += value[u];
        dp[u][0][1] += -value[u];
        dp[u][1][0] += -value[u] - cost[u];
        dp[u][1][1] += value[u] - cost[u];
    }
    if (dp[0][0][0] < 0) puts("HAHAHAOMG");
    else printf("%d\n",dp[0][0][0]);
}

int main()
{
    #ifdef ACM
        freopen("in.txt", "r", stdin);
    #endif // ACM
    while (scanf("%d%d%d",&n,&x,&y)==3) {
        input();
        solve();
    }
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值