树形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:一棵树最多两个重心)

 

posted @ 2019-05-17 16:20  codeoos  阅读(207)  评论(0编辑  收藏  举报