Codeforces 161D(树形dp)

(dp[v][k])代表以(v)的子树为起点,以点(v)为终点长度为(k)的方案有多少种。
转移只需将子树加和;计算(ans)由两部分组成,一是(dp[v][k]),另一部分是经过(v)的方案数。

#include <cstdio>
#include <vector>
using std::vector;

const int maxn = 5e4 + 5, maxk = 505;
int n, k, dp[maxn][maxk], ans;
vector<int> adj[maxn];

void dfs(int cur, int fa) {
	long long res = 0;
	dp[cur][0] = 1;
	for (int u : adj[cur])
		if (u != fa) {
			dfs(u, cur);
			for (int j = 0; j < k; j++)
				dp[cur][j + 1] += dp[u][j];
		}
	for (int u : adj[cur])
		if (u != fa) {
			for (int j = 1; j < k; j++)
				res += (long long)dp[u][j - 1] * (dp[cur][k - j] - dp[u][k - j - 1]);
		}
	ans += res / 2 + dp[cur][k];
}

int main(int argc, char const *argv[]) {
	scanf("%d %d", &n, &k);
	for (int u, v, i = 1; i < n; i++) {
		scanf("%d %d", &u, &v);
		adj[u].push_back(v);
		adj[v].push_back(u);
	}
	return dfs(1, 0), !printf("%d
", ans);
}
原文地址:https://www.cnblogs.com/AlphaWA/p/10807137.html