• 树形dp mark


    A - Anniversary party HDU - 1520 

    题意是 有一个树 每个点都有一个价值,选了父亲节点就不能选子节点 选了子节点就不能选父亲节点 

    问最后能得到的最大价值是多少

    树形dp入门  定义状态 dp[i][1]表示选中此节点 dp[i][0]表示未选中此节点

    那么 dp[i][1]=sigma(dp[j][0])+a[i]; //j为i的儿子节点

    dp[i][0]=sigma(max(dp[j][1],dp[j][0]))+a[i];

    另外无论如何都要吐槽一下这题的输入格式!!!!

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 int n;
     4 const int maxn=6060;
     5 
     6 vector<int>G[maxn];
     7 int v[6060];
     8 int dp[maxn][2];
     9 int pre[maxn];
    10 
    11 int dfs(int x)
    12 {
    13     dp[x][1]=v[x];
    14     for(int i=0;i<G[x].size();i++)
    15         dfs(G[x][i]);
    16     for(int i=0;i<G[x].size();i++)
    17     {
    18         dp[x][1]+=dp[G[x][i]][0];
    19         dp[x][0]+=max(dp[G[x][i]][1],dp[G[x][i]][0]);
    20     }
    21 }
    22 
    23 int main()
    24 {
    25     int x,y;
    26     while(~scanf("%d",&n)){
    27     for(int i=0;i<=n;i++) G[i].clear();
    28     for(int i=1;i<=n;i++) scanf("%d",&v[i]);
    29     memset(pre,-1,sizeof(pre));
    30     while(~scanf("%d%d",&x,&y))
    31     {
    32         if(x==0||y==0) break;
    33         G[y].push_back(x);
    34         pre[x]=y;
    35     }
    36 
    37     memset(dp,0,sizeof(dp));
    38 
    39     int root=1;
    40     while(pre[root]!=-1) root=pre[root];
    41     dfs(root);
    42     printf("%d
    ",max(dp[root][0],dp[root][1]));
    43 }
    44 }

    B - Computer

     HDU - 2196 

    给一个树 求每个节点能够到达的最远距离是多少?

    定义dp[i][0]为i节点向下走的最远距离,自下而上

    dp[i][1]为i节点向下走的次远距离,自下而上

    dp[i][2]为i节点向上走的最远距离,自上而下

    那么每一个节点能够到达的最远距离与 儿子节点到达的距离有关 与父亲节点到达的距离有关

    那么就需要两次dfs , 第一次自下而上 维护一个 dp[i][0],dp[i][1],

    第二次dfs 自上而下 维护一下 dp[i][2];

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 
     4 typedef pair<int,int> pii;
     5 
     6 const int maxn=1e4+5;
     7 
     8 int n;
     9 vector<pii >G[maxn];
    10 
    11 int dp[maxn][3];
    12 
    13 int dfs1(int u)
    14 {
    15     for(int i=0;i<G[u].size();i++)
    16     {
    17         int v=G[u][i].first;
    18         int w=G[u][i].second;
    19         dfs1(v);
    20         if(dp[u][0]<=dp[v][0]+w)
    21         {
    22             dp[u][1]=dp[u][0];
    23             dp[u][0]=dp[v][0]+w;
    24         }
    25         else if(dp[v][0]+w>dp[u][1])
    26             dp[u][1]=dp[v][0]+w;
    27     }
    28 }
    29 
    30 int dfs2(int u)
    31 {
    32     for(int i=0;i<G[u].size();i++)
    33     {
    34         int v=G[u][i].first;
    35         int w=G[u][i].second;
    36         if(dp[u][0]!=dp[v][0]+w)
    37         {
    38             dp[v][2]=max(dp[u][0]+w,dp[u][2]+w);
    39         }
    40         else{
    41             dp[v][2]=max(dp[u][1]+w,dp[u][2]+w);
    42         }
    43         dfs2(v);
    44     }
    45 }
    46 
    47 int main()
    48 {
    49     int x,y;
    50     while(~scanf("%d",&n))
    51     {
    52         for(int i=0;i<=n;i++) G[i].clear();
    53         for(int i=2;i<n+1;i++)
    54         {
    55             scanf("%d%d",&x,&y);
    56             G[x].push_back({i,y});
    57         }
    58 
    59         memset(dp,0,sizeof(dp));
    60 
    61         dfs1(1);
    62         dfs2(1);
    63 
    64         for(int i=1;i<=n;i++)
    65             printf("%d
    ",max(dp[i][0],dp[i][2]));
    66     }
    67 }
  • 相关阅读:
    ArcMap+ArcCatalog手工新建点层及添加数据
    zedGraph 图表控件总结(一)
    Android 开发学习笔记(五)—— 最简单的注册界面
    repeater实现删除按钮
    repeater分页实例
    FCKeditor的使用说明
    javascript:void(0)是什么意思
    为asp.net控件点击事件添加Confirm()
    LINQ判断素数
    U盘文件不能删除,怎么处理
  • 原文地址:https://www.cnblogs.com/hellohacker/p/7379835.html
Copyright © 2020-2023  润新知