Codeforces Round #607 (Div. 1) D. Miss Punyverse(dp树上背包)

题目链接:https://codeforc.es/contest/1280/problem/D

The Oak has n nesting places, numbered with integers from 1 to n. Nesting place i is home to bi bees and wi wasps.

Some nesting places are connected by branches. We call two nesting places adjacent if there exists a branch between them. A simple path from nesting place x to y is given by a sequence s0,…,sp of distinct nesting places, where p is a non-negative integer, s0=x, sp=y, and si−1 and si are adjacent for each i=1,…,p. The branches of The Oak are set up in such a way that for any two pairs of nesting places x and y, there exists a unique simple path from x to y. Because of this, biologists and computer scientists agree that The Oak is in fact, a tree.

A village is a nonempty set V of nesting places such that for any two x and y in V, there exists a simple path from x to y whose intermediate nesting places all lie in V.

A set of villages P is called a partition if each of the n nesting places is contained in exactly one of the villages in P. In other words, no two villages in P share any common nesting place, and altogether, they contain all n nesting places.

The Oak holds its annual Miss Punyverse beauty pageant. The two contestants this year are Ugly Wasp and Pretty Bee. The winner of the beauty pageant is determined by voting, which we will now explain. Suppose P is a partition of the nesting places into m villages V1,…,Vm. There is a local election in each village. Each of the insects in this village vote for their favorite contestant. If there are strictly more votes for Ugly Wasp than Pretty Bee, then Ugly Wasp is said to win in that village. Otherwise, Pretty Bee wins. Whoever wins in the most number of villages wins.

As it always goes with these pageants, bees always vote for the bee (which is Pretty Bee this year) and wasps always vote for the wasp (which is Ugly Wasp this year). Unlike their general elections, no one abstains from voting for Miss Punyverse as everyone takes it very seriously.

Mayor Waspacito, and his assistant Alexwasp, wants Ugly Wasp to win. He has the power to choose how to partition The Oak into exactly m villages. If he chooses the partition optimally, determine the maximum number of villages in which Ugly Wasp wins.

Input
The first line of input contains a single integer t (1≤t≤100) denoting the number of test cases. The next lines contain descriptions of the test cases.

The first line of each test case contains two space-separated integers n and m (1≤m≤n≤3000). The second line contains n space-separated integers b1,b2,…,bn (0≤bi≤109). The third line contains n space-separated integers w1,w2,…,wn (0≤wi≤109). The next n−1 lines describe the pairs of adjacent nesting places. In particular, the i-th of them contains two space-separated integers xi and yi (1≤xi,yi≤n, xi≠yi) denoting the numbers of two adjacent nesting places. It is guaranteed that these pairs form a tree.

It is guaranteed that the sum of n in a single file is at most 105.

Output
For each test case, output a single line containing a single integer denoting the maximum number of villages in which Ugly Wasp wins, among all partitions of The Oak into m villages.

Example

input

2
4 3
10 160 70 50
70 111 111 0
1 2
2 3
3 4
2 1
143 420
214 349
2 1

output

2
0

题意

给一棵树,树上每个点有两个权值,分别是 wi ,bi 。要求将树分成m个联通块,要求最多能有几个联通块内的∑ wi > ∑ bi 。

分析

我们从 1 号点开始遍历,dp[i][j] 表示 i 号点的子树被分成 j 个连通块时,最多有几个块满足条件。
我们再引入一个数组 a ,a[i] 表示 i 号点的子树所有点的 w 和 b 的差值,这样我们就可以判断当 i 号子树作为一个连通块的时候是否符合要求。
在 dp 时可以用 pair 来传递 a 的值。

代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,ll> pil;

const int N = 3e3 + 7;
int t,n,m,b[N],w[N],a[N];
vector<int> e[N];
pil f[N][N],tmp[N];
int sz[N];

inline void add(int a, int b)
{
	e[a].push_back(b);
	e[b].push_back(a);
}

inline void update(pil &a, pil b)
{
	if(a.first < b.first) a = b;
	else if(a.first == b.first && a.second < b.second) a = b;
}

void dfs(int u,int fa)
{
	sz[u] = 1;
	f[u][1] = pil(0, a[u]);
	for(int i=0;i<e[u].size();i++)
	{
		int v = e[u][i];
		if(v == fa) continue;
		dfs(v, u);
		for(int j=1;j<=sz[u]+sz[v];j++) tmp[j] = pil(-1, 0);
		for(int j=1;j<=sz[u];j++)
			for(int k=1;k<=sz[v];k++)
			{
				update(tmp[j + k], pil(f[u][j].first + f[v][k].first + (f[v][k].second > 0), f[u][j].second));
				update(tmp[j + k - 1], pil(f[u][j].first + f[v][k].first, f[u][j].second + f[v][k].second));
			}
		for(int j=1;j<=sz[u]+sz[v];j++) f[u][j] = tmp[j];
		sz[u] += sz[v];
	}
}

int main()
{
	scanf("%d",&t);
	while(t--)
	{
		scanf("%d%d",&n,&m);
		for(int i=1;i<=n;i++) scanf("%d",&b[i]);
		for(int i=1;i<=n;i++) scanf("%d",&w[i]), a[i] = w[i] - b[i];
		for(int i=1;i<n;i++)
		{
			int u,v;
			scanf("%d%d",&u,&v);
			add(u, v);
		}
		dfs(1, 0);
		printf("%d\n",f[1][m].first + (f[1][m].second > 0));
		for(int i=1;i<=n;i++)
		{
			for(int j=1;j<=sz[i];j++)
				f[i][j] = pil(0, 0);
			e[i].clear();
		}
	}
	return 0;
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值