CF 161D Distance in Tree 树形DP

一棵树,边长都是1,问这棵树有多少点对的距离刚好为k

令tree(i)表示以i为根的子树

dp[i][j][1]:在tree(i)中,经过节点i,长度为j,其中一个端点为i的路径的个数
dp[i][j][0]:在tree(i)中,经过节点i,长度为j,端点不在i的路径的个数

则目标:∑(dp[i][k][0]+dp[i][k][1])
初始化:dp[i][0][1]=1,其余为0

siz[i]:tree(i)中,i与离i最远的点的距离
递推:
dp[i][j][0]+=dp[i][j-l][1]*dp[soni][l-1][1]
dp[i][j][1]=∑dp[soni][j-1][1]

注意:在更新每一个dp[i]时,先更新dp[i][j][0],再更新dp[i][j][1]

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<iostream>
  4
  5 using namespace std;
  6
  7 const int maxn=50000+5;
  8 const int maxk=505;
  9 #define LL long long
 10
 11 inline int max(int a,int b)
 12 {
 13     return a>b?a:b;
 14 }
 15
 16 inline int min(int a,int b)
 17 {
 18     return a<b?a:b;
 19 }
 20
 21 LL dp[maxn][maxk][2];
 22 int siz[maxn];
 23 struct Edge
 24 {
 25     int to,next;
 26 };
 27 Edge edge[maxn<<1];
 28 int head[maxn];
 29 int tot;
 30 int k;
 31
 32 void init()
 33 {
 34     memset(head,-1,sizeof head);
 35     tot=0;
 36     memset(dp,0,sizeof dp);
 37 }
 38
 39 void addedge(int u,int v)
 40 {
 41     edge[tot].to=v;
 42     edge[tot].next=head[u];
 43     head[u]=tot++;
 44 }
 45
 46 void solve(int ,int );
 47 void dfs(int ,int );
 48
 49 int main()
 50 {
 51     init();
 52     int n;
 53     scanf("%d %d",&n,&k);
 54     for(int i=1;i<n;i++)
 55     {
 56         int u,v;
 57         scanf("%d %d",&u,&v);
 58         addedge(u,v);
 59         addedge(v,u);
 60     }
 61     solve(n,k);
 62     return 0;
 63 }
 64
 65 void solve(int n,int k)
 66 {
 67     dfs(1,0);
 68     LL ans=0;
 69     for(int i=1;i<=n;i++)
 70     {
 71         ans+=(dp[i][k][0]+dp[i][k][1]);
 72     }
 73     cout<<ans<<endl;
 74     return ;
 75 }
 76
 77 void dfs(int u,int pre)
 78 {
 79     dp[u][0][1]=1;
 80     siz[u]=0;
 81     for(int i=head[u];~i;i=edge[i].next)
 82     {
 83         int v=edge[i].to;
 84         if(v==pre)
 85             continue;
 86         dfs(v,u);
 87         for(int l=1;l<=siz[v]+1;l++)
 88         {
 89             for(int j=l+1;j<=siz[u]+l;j++)
 90             {
 91                 if(j>k)
 92                     continue;
 93                 dp[u][j][0]+=dp[u][j-l][1]*dp[v][l-1][1];
 94             }
 95         }
 96         for(int j=1;j<=siz[v]+1;j++)
 97             dp[u][j][1]+=dp[v][j-1][1];
 98         siz[u]=max(siz[u],siz[v]+1);
 99         siz[u]=min(siz[u],k);
100     }
101 }

时间: 2024-12-23 11:32:54

CF 161D Distance in Tree 树形DP的相关文章

codeforces161D - Distance in Tree 树形dp

题意:给你一棵树,问你树中距离为k的有多少种情况. 解题思路:树形dp  维护每个节点(1-K)深度的情况, 解题代码: 1 // File Name: 161d.cpp 2 // Author: darkdream 3 // Created Time: 2014年08月03日 星期日 19时20分10秒 4 5 #include<vector> 6 #include<list> 7 #include<map> 8 #include<set> 9 #incl

CF 461B Appleman and Tree 树形DP

Appleman has a tree with n vertices. Some of the vertices (at least one) are colored black and other vertices are colored white. Consider a set consisting of k (0 ≤ k < n) edges of Appleman's tree. If Appleman deletes these edges from the tree, then

codeforces 161D - Distance in Tree(树形dp)

题目大意: 求出树上距离为k的点对有多少个. 思路分析: dp[i][j] 表示 i 的子树中和 i 的距离为 j 的点数有多少个.注意dp[i] [0] 永远是1的. 然后在处理完一颗子树后,就把自身的dp 更新. 更新之前更新答案. 如果这颗子树到 i 有 x 个距离为j的.那么答案就要加上 dp[i] [ k-j-1] * x; #include <iostream> #include <cstdio> #include <cstring> #include &l

Bestcoder round #65 &amp;&amp; hdu 5593 ZYB&#39;s Tree 树形dp

Time Limit: 3000/1500 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)Total Submission(s): 354    Accepted Submission(s): 100 Problem Description ZYB has a tree with N nodes,now he wants you to solve the numbers of nodes distanced no m

hdu5593/ZYB&#39;s Tree 树形dp

ZYB's Tree Memory Limit: 131072/131072 K (Java/Others) 问题描述 ZYBZYB有一颗NN个节点的树,现在他希望你对于每一个点,求出离每个点距离不超过KK的点的个数. 两个点(x,y)(x,y)在树上的距离定义为两个点树上最短路径经过的边数, 为了节约读入和输出的时间,我们采用如下方式进行读入输出: 读入:读入两个数A,BA,B,令fa_ifa?i??为节点ii的父亲,fa_1=0fa?1??=0;fa_i=(A*i+B)\%(i-1)+1fa

URAL_1018 Binary Apple Tree 树形DP+背包

这个题目给定一棵树,以及树的每个树枝的苹果数量,要求在保留K个树枝的情况下最多能保留多少个苹果 一看就觉得是个树形DP,然后想出 dp[i][j]来表示第i个节点保留j个树枝的最大苹果数,但是在树形过程中,有点难表示转移 后来看了下大神的做法才知道其实可以用背包来模拟 树枝的去留,其实真的是个背包诶,每个子树枝就相当于物品,他占用了多少树枝量,带来多少的收益,就是用背包嘛,于是用树形DP+背包就可以做了 #include <iostream> #include <cstdio> #

CF 337D Book of Evil 树形DP 好题

Paladin Manao caught the trail of the ancient Book of Evil in a swampy area. This area contains n settlements numbered from 1 to n. Moving through the swamp is very difficult, so people tramped exactly n - 1 paths. Each of these paths connects some p

Codeforces 461B Appleman and Tree(树形dp)

题目链接:Codeforces 461B Appleman and Tree 题目大意:一棵树,以0节点为根节点,给定每个节点的父亲节点,以及每个点的颜色(0表示白色,1表示黑色),切断这棵树的k条边,使得树变成k+1个联通分量,保证每个联通分量有且仅有1个黑色节点.问有多少种分割方法. 解题思路:树形dp,dp[i][0]和dp[i][1]分别表示子树一下的分割方法中,i节点所在联通块不存在黑节点和已经存在一个黑节点的方案数. #include <cstdio> #include <c

hdu6035 Colorful Tree 树形dp 给定一棵树,每个节点有一个颜色值。定义每条路径的值为经过的节点的不同颜色数。求所有路径的值和。

/** 题目:hdu6035 Colorful Tree 链接:http://acm.hdu.edu.cn/showproblem.php?pid=6035 题意:给定一棵树,每个节点有一个颜色值.定义每条路径的值为经过的节点的不同颜色数.求所有路径的值和. 思路:看题解后,才想出来的.树形dp. 求所有路径的值和 = 路径条数*总颜色数(n*(n-1)*colors/2)-sigma(每种颜色没有经过的路径条数) 主要是求每种颜色没有经过的路径条数. 画一棵树,我直接用颜色值表示节点编号. 2