luogu P1272 重建道路 类似树上背包的树形dp

#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int N = 500;
int f[N][N];
int h[N], e[N], ne[N], idx;
int n, p;
int ans = 0x3f3f3f3f;
int in[N];
void add(int a, int b)
{
	e[idx] = b;
	ne[idx] = h[a];
	h[a] = idx ++;
}
void dfs(int u, int fa)
{
	f[u][1]=in[u];//只保留这一个节点,那么就把所有临边都砍掉
	for(int i = h[u]; i != -1; i = ne[i])
	{
		int v = e[i];
		if(v == fa)
			continue;
		dfs(v, u);
		//遍历完所有子节点,从下往上递归,
		//父节点开始的时候 默认为只有f[u][1]
		//当前子树去更新父节点信息的时候,默认这颗子树没有更新过
		//也就是说 父节点中的信息中 要砍掉的边(包含的点),是不包含当前子树中的节点的
		for(int j = p; j >= 1; j --)
			for(int k = 1; k < j; k ++)
				f[u][j] = min(f[u][j], f[u][k] + f[v][j - k] - 2);
	}
}
int main()
{
	memset(h, -1, sizeof h);
	cin >> n >> p;
	for(int i = 1; i < n; i ++)
	{
		int a, b;
		cin >> a >> b;
		in[a] ++ ;
		in[b] ++ ;
		add(a, b);
		add(b, a);
	}
	memset(f, 0x3f, sizeof f);
	dfs(1, -1);
	for(int i = 1; i <= n; i ++)
		ans = min(f[i][p], ans);
	cout << ans << endl;
	return 0;
}
上一篇:树与图的存储与遍历


下一篇:牛客 Treepath(树形dp)