histcat

histcat

P2015 二叉蘋果樹

題目#

二叉蘋果樹#

題目描述#

有一棵蘋果樹,如果樹枝有分叉,一定是分二叉(就是說沒有只有一個兒子的結點)

這棵樹共有 $N$ 個結點(葉子點或者樹枝分叉點),編號為 $1 \sim N$,樹根編號一定是 $1$。

我們用一根樹枝兩端連接的結點的編號來描述一根樹枝的位置。下面是一顆有 $4$ 個樹枝的樹:

2   5
 \ / 
  3   4
   \ /
    1

現在這棵樹枝條太多了,需要剪枝。但是一些樹枝上長有蘋果。

給定需要保留的樹枝數量,求出最多能留住多少蘋果。

解題#

設 f [i][j] 表示以 i 為子樹中保留 j 個樹枝能獲得的最大蘋果數

然後樹形 dp 即可

不過由於這題是二叉樹,所以我們可以先 dfs 處理出每一個節點的左右子樹,然後 dp 的時候可以直接使用。否則要枚舉 i 的子樹並倒序循環

AC 代碼#

#include<bits/stdc++.h>

using namespace std;

int n, q;

int read()
{
	int f = 1, x = 0;
	char ch = getchar();
	while(ch < '0' || ch > '9')
	{
		if(ch == '-') f = -1;
		ch = getchar();
	}

	while(ch >= '0' && ch <= '9')
	{
		x = x * 10 + ch - '0';
		ch = getchar();
	}
	return f * x;
}
const int N = 210;

int head[N], to[N], nxt[N], edge[N], cnt = 1;
int f[N][N], size[N]/*以i為子樹所含的邊的數量*/, lf[N], rf[N], lf_w[N], rf_w[N];


void add(int x, int y, int z)
{
	to[++cnt] = y;
	edge[cnt] = z;
	nxt[cnt] = head[x];
	head[x] = cnt;
}

void tongji(int u, int fa)
{
	for(int i = head[u]; i; i = nxt[i])
	{
		if(to[i] == fa) continue;
		tongji(to[i], u);
		size[u] += size[to[i]] + 1;
		if(lf[u] == 0) lf[u] = to[i], lf_w[u] = edge[i];
		else rf[u] = to[i], rf_w[u] = edge[i];
	}
}


int dp(int u, int j)
{
	if((!lf[u]) && (!rf[u])) return 0;
	if(f[u][j]) return f[u][j];
	if(j <= 0) return 0;
	int a = min(size[u], j);
	//分給左兒子 
	for(int k = 0;k <= a;k++)
	{
//		cout << u << " give left son " << k << "branches" << endl;
		if(k == 0)
		{
			f[u][j] = max(f[u][j], dp(rf[u], a - 1) + rf_w[u]);
//			cout << dp(rf[u], a - 1) + rf_w[u] << endl;
		}
		else if(a == k)
		{
			f[u][j] = max(f[u][j], dp(lf[u], a - 1) + lf_w[u]);
//			cout << dp(lf[u], a - 1) + lf_w[u] << endl;
		}
		else
		{
			f[u][j] = max(f[u][j], dp(lf[u], k - 1) + dp(rf[u], a - k - 1) + lf_w[u] + rf_w[u]);
//			cout << dp(lf[u], k - 1) + dp(rf[u], a - k - 1) + lf_w[u] + rf_w[u] << endl;
		}
	}
//	cout << u << " " << j  << ": " << f[u][j] << endl;
	return f[u][j];
}

int main()
{
	n = read(), q = read();

	int x, y, z;

	for(int i = 1;i <= n - 1;i++)
	{
		x = read(), y = read(), z = read();
		add(x, y, z);
		add(y, x, z);
	}
	tongji(1, 0);
	dp(1, q);
	cout << f[1][q];
	return 0;
}
載入中......
此文章數據所有權由區塊鏈加密技術和智能合約保障僅歸創作者所有。