概述
题意:给你一颗树,和一个数k,问树中长度为k的路径的条数.
分析:一看就是树形DP的类型.树形DP的特点就是用所有叶子节点的信息更新出其父亲节点,然后这些父亲节点再作为叶子节点,这样层层递归直到根节点.
这里很容易想到的一种叶子节点更新父亲节点的方式如下:
定义 dp[i][j] 为节点i为根的所有子树中长度为j的路径的条数.
那么就容易有:dp[i][j]=∑u(u为i的所有子节点)dp[u][j−1]
这样层层的递归调用就可以从子节点更新到根节点了.
但是样根据树的乘法原理算出路径数,还需要一边更新,一边计算.计算的原则是每往该节点加入一个分支,就用该分支和前面已经加入的分支总和来进行组合相乘.
Code:
#include <iostream>
#include <cstdio>
#include <vector>
using namespace std;
const int M = int(1e5 + 1), INF = 0x3fffffff, mod = 1000000007;
int dp[50009][509], n, k;
long long ans = 0;
vector<int> v[50009];
void dfs(int p, int prev)
{
int u;
dp[p][0] = 1;
for (int i = 0; i < v[p].size(); i++) {
u = v[p][i];
if (u == prev) continue; //只计算当前节点的只树的距离,根节点跳过
dfs(u, p);
for (int i = 0; i < k; i++)
ans += dp[p][i] * dp[u][k - i -1]; //把当前节点要加入的分支,并组合相乘更新答案
for (int i=0; i<k; i++)
dp[p][i + 1] += dp[u][i]; //由子树来更新当前节点
}
return;
}
int main(void)
{
cin >> n >> k;
for (int i = 0; i < n - 1; i++) {
int x, y;
cin >> x >> y;
v[x].push_back(y);
v[y].push_back(x);
}
dfs(n, -1);
cout << ans << endl;
return 0;
}
最后
以上就是诚心航空为你收集整理的codeforces 161D Distance in Tree (树形DP 经典题)的全部内容,希望文章能够帮你解决codeforces 161D Distance in Tree (树形DP 经典题)所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复