树形DP(2)-Hdu 4799 LIKE vs CANDLE

2024-05-10 16:32
文章标签 dp vs like hdu 树形 candle 4799

本文主要是介绍树形DP(2)-Hdu 4799 LIKE vs CANDLE,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

题目链接:2013长沙赛区区域赛题目 http://acm.hdu.edu.cn/showproblem.php?pid=4799

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 XPower 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 XPower Point to flip them anymore; instead, he need spend YPower 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



题意:若干微博账户形成了一个转发树(即一个有根树)。每个账户有自己的价值,每个账户也有自己的态度(赞或蜡烛)。如果一个账户的态度是“赞”,它的价值就会被加到“赞”的一边,反之亦然。Edward可以从“赞”的一边拿出X 的价值去翻转一个账户,即把它的态度换到相反的一边。但是Edward 发现,有的账户已经被别人翻转过了,对于这些账户,Edward就要花费Y的价值去翻转它们。一旦一个账户被翻转了一次,它的所有子账户也会被翻转一次。求“赞”的一边的价值总数与“蜡烛”一边的价值总数的最大差值。若最大差值为负数则输出“HAHAHAOMG”。

输入:N个账户,X flip一个没有fliped的账户需要的花费,Y flip一个已经fliped的账户需要的花费。

四个数:账户价值,转发来源,是否要被flip(1表示要),被flip之前的状态(1表示蜡烛,0表示like)


思路:DP,dp[i][0/1]表示是 第i个账户 是否被flip之后 的最大价值。

转移方程:dp[i][0] += max(dp[j][0],f[j][1] - (flip[j]?Y:X));

dp[i][1] += max(dp[j][1],f[j][0] - (flip[j]?Y:X));

代码如下:

//#pragma comment(linker,"/STACK:102400000,102400000")
#include<cstdio>
#include<algorithm>
#include<vector>
#include<cstring>
using namespace std;
#define maxn 50050
int dp[maxn][2];
int n,X,Y;
bool state;//表示当前的账户的zan或者蜡烛表示的价值是正还是负。
int v[maxn],f,s[maxn],p;
struct node{int t,nxt;
}edge[maxn<<1];
int head[maxn];
bool vis[maxn];
void solve(int u)
{vis[u] = 1;if(s[u])state ^= 1;if(state)v[u] = -v[u];dp[u][0] = v[u];dp[u][1] = -v[u];for (int i = head[u]; i!=-1; i = edge[i].nxt){int y = edge[i].t;if(!vis[y]){solve(y);dp[u][0] += max(dp[y][0],dp[y][1]-(s[y]?Y:X));dp[u][1] += max(dp[y][1],dp[y][0]-(s[y]?Y:X));}}if(s[u]) state ^= 1;
}
int main()
{while(scanf("%d%d%d",&n,&X,&Y)!=EOF){memset(dp,0,sizeof(dp));memset(head,-1,sizeof(head));memset(vis,0,sizeof(vis));int ind = 0;state = 0;for (int i = 1; i <= n; i++){scanf("%d%d%d%d",&v[i],&f,&s[i],&p);if(p) v[i] = -v[i];edge[ind].t = i;edge[ind].nxt = head[f];head[f] = ind++;}solve(0);if(dp[0][0] < 0)puts("HAHAHAOMG");else printf("%d\n",dp[0][0]);}return 0;
}

很抱歉,我这个程序在ZOJ上能过,在Hdu上就栈溢出RE了,应该是递归层数过深,可是手动扩栈了也不行,等什么时候过了再修改吧╮(╯▽╰)╭

这篇关于树形DP(2)-Hdu 4799 LIKE vs CANDLE的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/976968

相关文章

hdu4826(三维DP)

这是一个百度之星的资格赛第四题 题目链接:http://acm.hdu.edu.cn/contests/contest_showproblem.php?pid=1004&cid=500 题意:从左上角的点到右上角的点,每个点只能走一遍,走的方向有三个:向上,向下,向右,求最大值。 咋一看像搜索题,先暴搜,TLE,然后剪枝,还是TLE.然后我就改方法,用DP来做,这题和普通dp相比,多个个向上

hdu1011(背包树形DP)

没有完全理解这题, m个人,攻打一个map,map的入口是1,在攻打某个结点之前要先攻打其他一个结点 dp[i][j]表示m个人攻打以第i个结点为根节点的子树得到的最优解 状态转移dp[i][ j ] = max(dp[i][j], dp[i][k]+dp[t][j-k]),其中t是i结点的子节点 代码如下: #include<iostream>#include<algorithm

hdu4865(概率DP)

题意:已知前一天和今天的天气概率,某天的天气概率和叶子的潮湿程度的概率,n天叶子的湿度,求n天最有可能的天气情况。 思路:概率DP,dp[i][j]表示第i天天气为j的概率,状态转移如下:dp[i][j] = max(dp[i][j, dp[i-1][k]*table2[k][j]*table1[j][col] )  代码如下: #include <stdio.h>#include

usaco 1.3 Mixing Milk (结构体排序 qsort) and hdu 2020(sort)

到了这题学会了结构体排序 于是回去修改了 1.2 milking cows 的算法~ 结构体排序核心: 1.结构体定义 struct Milk{int price;int milks;}milk[5000]; 2.自定义的比较函数,若返回值为正,qsort 函数判定a>b ;为负,a<b;为0,a==b; int milkcmp(const void *va,c

usaco 1.1 Broken Necklace(DP)

直接上代码 接触的第一道dp ps.大概的思路就是 先从左往右用一个数组在每个点记下蓝或黑的个数 再从右到左算一遍 最后取出最大的即可 核心语句在于: 如果 str[i] = 'r'  ,   rl[i]=rl[i-1]+1, bl[i]=0 如果 str[i] = 'b' ,  bl[i]=bl[i-1]+1, rl[i]=0 如果 str[i] = 'w',  bl[i]=b

Android平台播放RTSP流的几种方案探究(VLC VS ExoPlayer VS SmartPlayer)

技术背景 好多开发者需要遴选Android平台RTSP直播播放器的时候,不知道如何选的好,本文针对常用的方案,做个大概的说明: 1. 使用VLC for Android VLC Media Player(VLC多媒体播放器),最初命名为VideoLAN客户端,是VideoLAN品牌产品,是VideoLAN计划的多媒体播放器。它支持众多音频与视频解码器及文件格式,并支持DVD影音光盘,VCD影

poj 3974 and hdu 3068 最长回文串的O(n)解法(Manacher算法)

求一段字符串中的最长回文串。 因为数据量比较大,用原来的O(n^2)会爆。 小白上的O(n^2)解法代码:TLE啦~ #include<stdio.h>#include<string.h>const int Maxn = 1000000;char s[Maxn];int main(){char e[] = {"END"};while(scanf("%s", s) != EO

hdu 2093 考试排名(sscanf)

模拟题。 直接从教程里拉解析。 因为表格里的数据格式不统一。有时候有"()",有时候又没有。而它也不会给我们提示。 这种情况下,就只能它它们统一看作字符串来处理了。现在就请出我们的主角sscanf()! sscanf 语法: #include int sscanf( const char *buffer, const char *format, ... ); 函数sscanf()和

hdu 2602 and poj 3624(01背包)

01背包的模板题。 hdu2602代码: #include<stdio.h>#include<string.h>const int MaxN = 1001;int max(int a, int b){return a > b ? a : b;}int w[MaxN];int v[MaxN];int dp[MaxN];int main(){int T;int N, V;s

hdu 1754 I Hate It(线段树,单点更新,区间最值)

题意是求一个线段中的最大数。 线段树的模板题,试用了一下交大的模板。效率有点略低。 代码: #include <stdio.h>#include <string.h>#define TREE_SIZE (1 << (20))//const int TREE_SIZE = 200000 + 10;int max(int a, int b){return a > b ? a :