ZOJ 3734 LIKE vs CANDLE

  题目意思:(13年长沙站的一道水DP,本人也去了,当时太水笔) 说俩个人竞争选票,每个人可以随机选择支持谁。每个人带有权重不同。

现在已经结束了投票阶段,你一个骇客 支持LIKE  你写了一个软件可以 用LIKE 的 X点能量翻转某个个节点,这个节点的儿子也一样跟着翻转(转自他的就是他的儿子,孙子也一样,支持的人变了);

  有的点已经被人用   同样   的方法翻转过。这样的先需用Y能量,问LIKE-CANDLE最大和最小值:

  解法:对于每个节点最多一次操作,对吧,不解释;所以DP[num][flag]//代表LIKE-CANDLE最大和最小值:

多以我们只要维护俩个值支持LINK-CANDLE就可以了;

  代码注释如下:

#include <cstring>
#include <cmath>
#include <algorithm>
#include <cstdio>
#include <cstdlib>
using namespace std;
const int maxn=50001;
struct Edge
{
    int to,pre;
    Edge(int to=0,int pre=0):to(to),pre(pre){}
};
Edge edge[maxn<<1];
int head[maxn],pos;
int val[maxn];
int used[maxn];
int suport[maxn];
int n,x,y;
int dp[maxn][2];
void inint()
{
    memset(head,-1,sizeof(head));
    pos=0;
}
void add_edge(int s,int to)
{
    edge[pos]=Edge(to,head[s]);
    head[s]=pos++;
}
void dfs(int s,int cnt)
{

    int ans,key;
    if(used[s])cnt++;
    if( ((cnt&1) && (suport[s]==1)||( !(cnt&1) &&(suport[s]==0)  ) ))
    {
        dp[s][0]=val[s];
        dp[s][1]=-val[s];
    }
    else
    {
        dp[s][0]=-val[s];
        dp[s][1]=val[s];
    }//上面是初始化初始的权值
    for(int i=head[s];~i;i=edge[i].pre)
    {
        Edge &tmp=edge[i];
        dfs(tmp.to,cnt);
        dp[s][0]+=dp[tmp.to][0];
        dp[s][1]+=dp[tmp.to][1];
    }
  //这是整棵树的最大最小
if(s) { int need; if(used[s])need=y; else need=x; dp[s][0]=max(dp[s][0],dp[s][1]-need); dp[s][1]=max(dp[s][1],dp[s][0]-need); }
  //中是否翻转后的最大和最小 }
int main() { int s; while(~scanf("%d%d%d",&n,&x,&y)) { inint(); for(int i=1;i<=n;i++) { scanf("%d%d%d%d",&val[i],&s,&used[i],&suport[i]); add_edge(s,i); } dfs(0,0); if(dp[0][0]>=0) printf("%d\n",dp[0][0]); else puts("HAHAHAOMG"); } return 0; }

 

posted @ 2014-07-30 11:57  默默无语敲代码  阅读(236)  评论(0编辑  收藏  举报