您的位置:首页 > 其它

HDU 4799 树形DP

2017-10-05 22:26 369 查看

题意

微博投票,有两种投票选择方式,一种是选择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 0x3f3f3f3f
using 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");
}
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: