洛谷P1272 & 保留p个节点的最小删除边的数目 &树形dp

在这里插入图片描述

洛谷P1272

#include<iostream>

using namespace std;

#define MAXN 200
#define inf 0x300

struct edge {	//树的边
	int v;
	int next;
}e[MAXN];
//size[i]为以i为根的树的节点数目
int first[MAXN], size[MAXN], p;
int f[MAXN][MAXN][2];	//f[i][j][]表示以i为根节点,保留j个节点
//所需要删去的边的最小数目
//f[i][x][0]表示以i为根的树中,获得一棵x个节点的子树(不含i),最少需要删除多少边
//f[i][x][1]表示以i为根的树中,获得一棵x个节点的子树(含i),最少需要删除多少边

int min(int x, int y)
{
	if (x < y)
		return x;
	return y;
}
void ini(int n);
void dfs(int index);
void add(int index, int x, int y);

int main()
{
	int n;
	cin >> n >> p;
	for (int i = 1; i < n; i++)
	{
		int x, y;
		cin >> x >> y;
		add(i, x, y);
	}

	ini(n);
	dfs(1);
	cout << min(f[1][p][0], f[1][p][1]);
	return 0;
}

void ini(int n)
{
	for (int i = 1; i <= n; i++)
		for (int j = 0; j <= p; j++)
			for (int k = 0; k <= 1; k++)
				f[i][j][k] = inf;
}

void dfs(int index)
//遍历以index为根的树
{
	f[index][0][0] = f[index][1][1] = 0;
	size[index] = 1;

	for (int l = first[index]; l; l = e[l].next)
		//遍历所有index的子节点
	{
		int v = e[l].v;
		dfs(v);	//遍历子节点以得到子节点的数目,此时没有删边
		size[index] += size[v];
		int tmp[MAXN];
		for (int x = 1; x <= min(p, size[index]); x++)	//遍历所有可能的结点数
		{
			//min里的第二个为不删除index->x的边
			//min里的第三个为删除index->x的边
			f[index][x][0] = min(f[index][x][0], min(f[v][x][0], f[v][x][1] + 1));
			tmp[x] = inf;
			//表示都不删除
			for (int y = 1; y <= min(x - 1, size[v]); y++)
				tmp[x] = min(tmp[x], f[index][x - y][1] + f[v][y][1]);
			tmp[x] = min(tmp[x], f[index][x][1] + 1);
		}
		for (int x = 1; x <= min(p, size[index]); x++)
			f[index][x][1] = tmp[x];
	}
}

void add(int index, int x, int y)
//加树的边
{
	e[index].v = y;
	e[index].next = first[x];
	first[x] = index;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值