Tree 二分+树形dp

链接:https://ac.nowcoder.com/acm/contest/560/I
来源:牛客网
 

题目描述

You have a tree with N nodes and N-1 edges. Each node has a weight. The i-th node's weight is Wi. 
Now you should divide the N nodes into K connected parts . Each part has at least one node.
The sum of all node's Wi in a part is X. The minimum X of all parts is Y. You need to calculate maximum Y.

输入描述:

The first line contains two integers N and K(1≤K≤N≤100000)

链接:https://ac.nowcoder.com/acm/contest/560/I
来源:牛客网
 

示例1

输入

复制

5 3
1 2
1 3
2 4
2 5
1 2 3 4 5

输出

复制

4

题意:把一个树分成k部分,每一部分权值相加,让最小值最大,输出最小值

题解:二分答案,节点u累计的权值符合条件时,就吧这一部分截下来

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e5+10;
int n,k;
ll mid;
vector<int> v[N];
ll dp[N];
int flag;
int val[N];
void dfs(int u,int fa)
{
	dp[u]=val[u];
	for(int i=0;i<v[u].size();i++)
	{
		int to=v[u][i];
		if(to==fa) continue;
		dfs(to,u);
		dp[u]+=dp[to];
	}
//	cout<<u<<" "<<dp[u]<<" "<<mid<<endl;
	if(dp[u]>=mid)
	{
		dp[u]=0;
		flag++;
	}
}
int main()
{
	scanf("%d%d",&n,&k);
	int x,y;
	for(int i=1;i<n;i++)
	{
		scanf("%d%d",&x,&y);
		v[x].push_back(y);
		v[y].push_back(x);
	}
	for(int i=1;i<=n;i++) scanf("%d",&val[i]);
	ll l=1,r=1e10;
	ll ans=0;
	while(l<=r)
	{
		mid=(r+l)>>1;
		flag=0;
		dfs(1,0);
		
		if(flag>=k)
		{
			ans=mid;
			l=mid+1;
		}
		else r=mid-1;
	}
	cout<<ans<<endl;
	return 0;
 } 

猜你喜欢

转载自blog.csdn.net/mmk27_word/article/details/89284039