题意:
若干微博账户形成了一个转发树(即一个有根树)。
求“赞”的一边的价值总数与“蜡烛”一边的价值总数的最大差值。若最大差值为负数则输出“HAHAHAOMG”。
like - candle ,中间牵扯到了反转的问题。
首先可以想到需要 记录 like-candle的最大值 。
现在分析 like - candle可以由哪些子状态得到。
对于每个节点 有 翻转和不翻转两种状态。
那么用dp[u][0] 表示翻转后 like -candle 最大值。dp[u][1]表示不翻转 like-candle最大值
既然是树形dp就要考虑子节点v状态向父节点u状态的转移。每个子节点在转移到父节点的状态时,就考虑翻转和不翻转两种情况。
初始化: dp[u][0]=val[u],dp[u][1]=-val[u];
dp[u][0]=∑max(dp[v][0],dp[v][1]+翻转代价);
dp[u][1]=∑max(dp[v][1],dp[v][0]+翻转代价);
#include <stdio.h> #include <string.h> #include <stdlib.h> #include <algorithm> #include <vector> #define MAXN 50008 #define INF 0x3f3f3f3f using namespace std; vector<int> g[MAXN]; int val[MAXN]; int f[MAXN]; int s[MAXN]; int p[MAXN]; int dp[MAXN][2]; void init() { for(int i=0;i<MAXN;++i) { g[i].clear(); } } void dfs(int u,int x,int y,int st) { st+=s[u]; if(((st&1)&&!p[u]) || ((st%2==0)&&p[u])) val[u]=-val[u]; dp[u][0]=val[u],dp[u][1]=-val[u]; for(int i=0;i<g[u].size();++i) { int v=g[u][i]; dfs(v,x,y,st); dp[u][0]+=max(dp[v][0],dp[v][1]-(s[v]?y:x)); dp[u][1]+=max(dp[v][1],dp[v][0]-(s[v]?y:x)); } } int main() { int n,x,y; while(~scanf("%d%d%d",&n,&x,&y)) { init(); int v,far,fip,like; for(int i=1;i<=n;++i) { scanf("%d%d%d%d",&v,&far,&fip,&like); val[i]=v,g[far].push_back(i),s[i]=fip,p[i]=like; } dfs(0,x,y,0); if(dp[0][0]<0) printf("HAHAHAOMG\n"); else printf("%d\n",dp[0][0]); } return 0; }