• HDU 5834 Magic boy Bi Luo with his excited tree(树形dp)


    http://acm.hdu.edu.cn/showproblem.php?pid=5834

    题意:

    一棵树上每个节点有一个价值$Vi$,每个节点只能获得一次,每走一次一条边要花费$Ci$,问从各个节点出发最多能收获多少价值。

    思路:

    需要考虑子节点和父亲节点两个方面。既然是这样,那就需要两次dfs来解决问题了,$dp[u][0]$表示从u出发最后还是回到u的最大价值和,$dp[u][1]$表示从u出发最后不回到u的最大价值和。

    第一次dfs很显然就是计算出每个节点往其子树方向的$dp[u][0]$和$dp[u][1]$值。

    第二次dfs就是再去考虑每个节点加上其父节点的情况,这里就需要维护一个最大值和一个次大值了,为什么呢?因为父节点的最大值可能最后停在了v子树,那么v子树到时候再去考虑父节点的时候就不对了,所以此时要将它改成次大值,这样它的最大值最后不会停在v子树。

    总而言之,这是一道很经典的树形dp,不过没写出来。。

      1 #include<iostream>
      2 #include<algorithm>
      3 #include<cstring>
      4 #include<cstdio>
      5 #include<vector>
      6 #include<stack>
      7 #include<queue>
      8 #include<cmath>
      9 #include<map>
     10 #include<set>
     11 using namespace std;
     12 typedef long long ll;
     13 typedef pair<int,int> pll;
     14 const int INF = 0x3f3f3f3f;
     15 const int maxn=1e5+5;
     16 
     17 int n;
     18 int val[maxn];
     19 int dp[maxn][2];
     20 vector<pll> G[maxn];
     21 
     22 void dfs1(int u, int fa)  //求出每个顶点往子树方向的最大值,dp[u][0]表示最终回到u,dp[u][1]表示最终不回到u
     23 {
     24     dp[u][0]=dp[u][1]=val[u];
     25     for(int i=0;i<G[u].size();i++)
     26     {
     27         int v=G[u][i].first;
     28         int w=G[u][i].second;
     29         if(v==fa)  continue;
     30         dfs1(v,u);
     31         if(dp[v][0]-2*w>0)  dp[u][0]+=dp[v][0]-2*w;
     32     }
     33     for(int i=0;i<G[u].size();i++)
     34     {
     35         int v=G[u][i].first;
     36         int w=G[u][i].second;
     37         if(v==fa)  continue;
     38         int tmp = dp[u][0]-max(0,dp[v][0]-2*w)+(dp[v][1]-w);
     39         if(dp[u][1]<tmp)  dp[u][1]=tmp;
     40     }
     41 }
     42 
     43 void dfs2(int u, int fa, int cost)  //处理往父亲节点的方向
     44 {
     45     int dir_tree=u;
     46     if(fa!=-1)  if(dp[fa][0]-2*cost>0)  dp[u][0]+=dp[fa][0]-2*cost;
     47     int sub_large=dp[u][1]=dp[u][0];
     48     for(int i=0;i<G[u].size();i++)
     49     {
     50         int v=G[u][i].first;
     51         int w=G[u][i].second;
     52         int tmp=dp[u][0]-max(0,dp[v][0]-2*w)+(dp[v][1]-w);
     53         if(tmp>=dp[u][1])  //计算最大权值和次大权值
     54         {
     55             sub_large=dp[u][1];
     56             dp[u][1]=tmp;
     57             dir_tree=v;
     58         }
     59         else if(tmp>=sub_large)   sub_large=tmp;
     60     }
     61     int pre0=dp[u][0],pre1=dp[u][1];  //出去该父节点对其子节点的影响
     62     for(int i=0;i<G[u].size();i++)
     63     {
     64         int v=G[u][i].first;
     65         int w=G[u][i].second;
     66         if(v==fa)  continue;
     67         int tmp=dp[v][0]-2*w;
     68         if(tmp>0)  dp[u][0]-=tmp;  //子节点v往父节点走时,肯定不会再算v节点的子树
     69         if(dir_tree==v)  dp[u][1]=sub_large; //如果u的最大值最后停留在v子树,则改成次大值
     70         if(tmp>0)  dp[u][1]-=tmp;  //和上面的第2句相同
     71         dfs2(v,u,w);
     72         dp[u][0]=pre0,dp[u][1]=pre1;
     73     }
     74 
     75 }
     76 
     77 int main()
     78 {
     79     //freopen("in.txt","r",stdin);
     80     int T;
     81     int kase=0;
     82     scanf("%d",&T);
     83     while(T--)
     84     {
     85         scanf("%d",&n);
     86         for(int i=1;i<=n;i++)  {G[i].clear();scanf("%d",&val[i]);}
     87         for(int i=1;i<n;i++)
     88         {
     89             int u,v,w;
     90             scanf("%d%d%d",&u,&v,&w);
     91             G[u].push_back(make_pair(v,w));
     92             G[v].push_back(make_pair(u,w));
     93         }
     94         printf("Case #%d:
    ",++kase);
     95         dfs1(1,-1);
     96         dfs2(1,-1,0);
     97         for(int i=1;i<=n;i++)  printf("%d
    ",dp[i][1]);
     98     }
     99     return 0;
    100 }
  • 相关阅读:
    linux项目部署学习(1) pyhton3的虚拟环境virtualenv和virtualenvwrapper详解
    linux下pip查看安装包的路径、和指定安装目录
    python+selenium实现长截图
    selenium设置chrome浏览器保持登录方式两种options和cookie
    linux中离线安装django
    理解 bashrc 和 profile
    Django部署阿里云服务时候报错:SQLite 3.8.3 or later is required (found 3.7.17)
    Django的django-admin工具详解
    Yum Install --Downloadonly 离线下载依赖包研究
    分治法求n个点中的最近距离
  • 原文地址:https://www.cnblogs.com/zyb993963526/p/7442451.html
Copyright © 2020-2023  润新知