LIKE vs CANDLE
Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 327680/327680 K (Java/Others)
Total Submission(s): 540 Accepted Submission(s): 173
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 ith line means the ith account. Each line has four integers: V (0 ≤ V ≤ 1000) - the value of the ith account, F (0 ≤ F ≤ N) - which account did the ith account's forwarding account come from (0th 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
2013 Asia Changsha Regional Contest
长沙居然也举办过regional……
大致题意是,有一个原始的微博,然后大家都去转发它,转发的时候用LIKE和CANDLE分别表示支持和不支持。然后每个人都可以转发其他的微博(可以是原始的也可以是转发的),每个微博都有一定的价值,要计算支持的价值与不支持的价值差最大是多少。你可以选择花X价值去反转一些人的态度,每次反转之后,相应的所有转发过这个人微博的人的态度也会跟着反转。但是有一些微博已经被其他人反转过了,那么你要再次反转它得花价值Y。然后问最后价值差最大是多少。
转换过来就是一棵树,表示相互转发的关系。如果我反转节点i,那么i的所有后代都要被反转。然后每个节点都有一个值代表支持或者反对,还有一个值代表之前是否已经被修改过,另外还有点权。相当于是,找出一种方案,是得这个树中,带上正负之后的点权值最大是多少。
那么,这样显然就是一个树形dp的问题了。我们用dp[i][j]表示第i个节点被反转j次的最大权值和。注意到每个节点只能是支持或者不支持,所以没必要枚举反转次数,只需要枚举最后该点是支持还是不支持。于是改用dp[i][1]和dp[i][0]分别表示节点i被不支持和支持时的最大权值和。接下来考虑转移显然有转移方程dp[i][0]=Σmax(dp[son][0],dp[son][1]-(flip[son]?Y:X));dp[i][1]=Σmax(dp[son][1],dp[son][0]-(flip[son]?Y:X))。其中flip[i]表示节点i是否之前就被反转,用来决定反转时的代价。然后,我们还要加上节点i自己的权值,注意到我们虽然枚举了节点i最后是支持还是不支持,但是由于一些点原本已经被修改,然后这个修改也是连锁的,所以我们还要看该点被几个这样的预先修改的点修改了。为了处理这个问题,我们设置一个status,表示dfs当前位置的状态,初始status为0,每次异或flip[i]的值,如果flip[i]为1,那么状态反转。有了这个status,我们在看节点i时,如果status为1,那么说明他还要额外反转一次,否则不用。如此处理加上权值即可。
感觉还是有点没有说清楚,具体见代码吧: