zoukankan      html  css  js  c++  java
  • hdu4799 树型DP

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

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

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

    题解:说实话觉得特别绕,dp[n][2]两个状态一个表示翻转能得到的最大价值,一个表示不翻转能得到的最大价值。翻转的花费在父节点那一层计算更好算,因为最终的0节点是无法操作的,所以在那算很方便。有个trick就是初始就被转过的点的影响依然在子节点中,所以要用sta标记,,,,

     1 #include<cstdio>
     2 #include<iostream>
     3 #include<cstring>
     4 #include<string>
     5 #include<algorithm>
     6 #include <cmath>
     7 using namespace std;
     8 typedef long long ll;
     9 const ll INF = 1000000000000000000ll + 10 ;
    10 const double eps = 1e-8;
    11 const int maxn = 5e4 + 10;
    12 const double PI = acos(-1);
    13 int dp[maxn][2],head[maxn],val[maxn],ss[maxn],ff[maxn],cnt;
    14 bool sta;
    15 struct st{
    16     int to,nxt;
    17 }edge[maxn*2];
    18 int n,x,y;
    19 void add(int u,int v){
    20     edge[cnt].to = v;
    21     edge[cnt].nxt = head[u];
    22     head[u] = cnt;
    23     cnt++;
    24 }
    25 void dfs(int u,int pre){
    26     if(ss[u]) sta = !sta;
    27     if(sta) val[u] = -val[u];
    28     dp[u][0] = val[u];
    29     dp[u][1] = -val[u];
    30     for(int i = head[u];i != -1;i = edge[i].nxt){
    31         int v = edge[i].to;
    32         if(v == pre) continue;
    33         dfs(v,u);
    34         dp[u][0] += max(dp[v][0],dp[v][1] - (ss[v]?y:x));
    35         dp[u][1] += max(dp[v][1],dp[v][0] - (ss[v]?y:x));
    36     }
    37     if(ss[u]) sta = !sta;
    38 }
    39 void init(){
    40     cnt = 0;
    41     memset(dp,0,sizeof(dp));
    42     memset(head,-1,sizeof(head));
    43 }
    44 int main()
    45 {
    46   //  freopen("in.txt","r",stdin);
    47     while(~scanf("%d%d%d",&n,&x,&y)){
    48         init();
    49         int fr;
    50         for(int i = 1;i <= n;i++){
    51             scanf("%d%d%d%d",&val[i],&fr,&ss[i],&ff[i]);
    52             if(ff[i]) val[i] = -val[i];
    53             add(fr,i);
    54         }
    55         sta = false;
    56         dfs(0,-1);
    57         if(dp[0][0] < 0) cout<<"HAHAHAOMG"<<endl;
    58         else  printf("%d
    ",dp[0][0]);
    59     }
    60         return 0;
    61 }
  • 相关阅读:
    eclipse集成JBPM
    一个简单的NoSQL内存数据库—Berkeley DB基本操作的例子
    Berkely DB Java Edition学习笔记
    jsp和java获取文件或路径
    【Bzoj 1835 基站选址】
    【The Time Traveller's Wife】
    【Codeforces Round #430 (Div. 2) A C D三个题】
    【AIM Tech Round 4 (Div. 2) D Prob】
    【Codeforces AIM Tech Round 4 (Div. 2) C】
    【QAQ的Minecraft】
  • 原文地址:https://www.cnblogs.com/shimu/p/5929403.html
Copyright © 2011-2022 走看看