HDU 4799 树形DP

来源:互联网 发布:flower dance知乎 编辑:程序博客网 时间:2024/06/06 16:52

题意

微博投票,有两种投票选择方式,一种是选择LIKE,另一种是选择CANDLE。允许进行一些翻转操作,有一些点是已经被别人翻转过的,对于这些点我们翻转需要消耗Y的票数,对于其他的点我们翻转需要消耗X的票数。问我们最多可以得到LIKE-CANDLE票数最大值是多少。

题解

题目很难读,有很多坑。比如说给的投票状态是最初的状态,也就是别人还没有反转的状态,因此如果别人翻转了的话,我们还需要在DFS的过程中进行反转。
另外的话,对于反转消耗的计算,我们可以在父状态DP的时候进行计算。(因为是否翻转不仅仅由当前状态决定,还由父状态决定,如果父状态已经反转了,那么子状态默认就是反转的,因此需要在父状态时候判定消耗)
至于其他的也就没什么了,由于数据范围不大,因此直接树形DP就可以了。

代码

#include<bits/stdc++.h>#define UP(i,l,h) for(int i=l;i<h;i++)#define W(t) while(t)#define MEM(a,b) memset(a,b,sizeof(a))#define MAXN 100010#define INF 0x3f3f3f3fusing namespace std;int X[2];vector<int> son[50010];int p[50010],s[50010],val[50010];int dp[50010][2];void dfs(int u,int d){    d^=s[u];//    cout<<u<<" "<<d<<endl;    if(p[u]) val[u]=-val[u];    if(d) val[u]=-val[u];    dp[u][0]=val[u];    dp[u][1]=-val[u];//    cout<<u<<" "<<dp[u][0]<<" "<<dp[u][1]<<endl;    for(int v:son[u]){        dfs(v,d);        dp[u][0]+=max(dp[v][0],dp[v][1]-X[s[v]]);        dp[u][1]+=max(dp[v][1],dp[v][0]-X[s[v]]);    }}int main(){    int n;    W(~scanf("%d%d%d",&n,&X[0],&X[1])){        MEM(dp,0);        MEM(son,0);        int f;        UP(i,1,n+1){            scanf("%d%d%d%d",&val[i],&f,&s[i],&p[i]);            son[f].push_back(i);        }        dfs(0,0);        int ans=dp[0][0];        if(ans>=0){            printf("%d\n",ans);        }else{            puts("HAHAHAOMG");        }    }}
原创粉丝点击