zoukankan      html  css  js  c++  java
  • 树形dp学习笔记

      最近学习树形dp,刷了树形dp入门6题,https://cn.vjudge.net/contest/283650#problem/F,(感谢NEUQ整理)来写一下总结

      树形dp:故名思议,把dp放在 树上进行,利用树的父子关系进行转移

          注意:(1)做题过程中一定要牢记这是一棵树;

             (2)大多数树形dp都是从下往上递归进行(也有从下往上的);

      1.和<上司的舞会>题意类似(一样?)对于每个节点有两种状态,dp[n][0]表示这个点不选的情况下以这个点作为祖先的树的最优情况,dp[n][1]表示选这个点的情况下以这个点作为祖先的树的最优情况.由此,我们可以很快得出转移方程:

      dp[now][1]+=min(dp[to][1],dp[to][0]);

      dp[now][0]+=dp[to][1]//如果不选这个点,那么必选其子节点.

    -----------------------------------------------------在去北京的动车上突然很困.....先睡一会,咕咕咕----------------------------------------------------------  

    这一咕,就是好久啊....

      2.

      求一棵树的最小点覆盖(要求把一些点染色,使得每个点都邻近一个染色的点或者这个点被染色)

      这个也没什么难度,直接上转移方程

      dp[i][0/1]表示点i没染色/被染色时,以i为根节点的树的被染色点数最小值

      dp[now][0]+=dp[to][1]

      dp[now][1]+=min(dp[to][1],dp[to][0]);

      3.

      给你一棵树,这棵树有n个点,让你找到一些点,把这些点去掉任何一个以后,使得剩下的每一棵树的大小都不超过n/2,找到这个点集.

      分析一下可知:这道题就是要找树的中心.

      复习:

      树的中心有如下性质:  

    1. 树中所有点到某个点的距离和中,到重心的距离和是最小的,如果有两个距离和,他们的距离和一样。
    2. 把两棵树通过一条边相连,新的树的重心在原来两棵树重心的连线上。
    3. 一棵树添加或者删除一个节点,树的重心最多只移动一条边的位置。
    4. 一棵树最多有两个重心,且相邻.
       代码:
      
     1 #include<iostream>
     2 #include<vector>
     3 using namespace std;
     4 const int maxn=1e4+5;
     5 int cnt[maxn];//以自己为祖先的子树的大小
     6 int n;
     7 int dp[maxn];
     8 vector<int>G[maxn];
     9 void dfs(int now,int fa)
    10 {
    11     cnt[now]=1;
    12     for(int i=0;i<G[now].size();++i)
    13     {
    14         int to=G[now][i];
    15         if(to==fa) continue;
    16         dfs(to,now);
    17         cnt[now]+=cnt[to];
    18     }
    19     dp[now]=n-cnt[now];//注意此处处理:在树形cnt的时候,记住与一个点相连的不仅是它的儿子,还有它的父亲
    20                        //把自己当做祖先,原来的父节点当做一个子节点,求这个子节点(原来的父节点)的数量,用n-cnt[自己]
    21     for(int i=0;i<G[now].size();++i)
    22     {
    23         int to=G[now][i];
    24         if(to==fa) continue;
    25         dp[now]=max(dp[now],cnt[to]);
    26     }
    27 }
    28 int main()
    29 {
    30     ios::sync_with_stdio(0);
    31     cin>>n;
    32     for(int i=2;i<=n;++i)
    33     {
    34         int a,b;cin>>a>>b;
    35         G[a].push_back(b);
    36         G[b].push_back(a);
    37     }
    38     dfs(1,-1);
    39     for(int i=1;i<=n;++i)
    40     {
    41         if(dp[i]<=n/2) cout<<i<<endl;
    42     }
    43 }

      (ps:一棵树最多两个重心)

  • 相关阅读:
    【PyTorch深度学习60分钟快速入门 】Part1:PyTorch是什么?
    如何编写一个gulp插件
    进阶之初探nodeJS
    模拟Vue之数据驱动5
    模拟Vue之数据驱动4
    模拟Vue之数据驱动3
    模拟Vue之数据驱动2
    树结构之JavaScript
    模拟Vue之数据驱动1
    CORS详解[译]
  • 原文地址:https://www.cnblogs.com/codeoosacm/p/10881957.html
Copyright © 2011-2022 走看看