1. 程式人生 > 實用技巧 >CodeForces - 1436D Bandit in a City

CodeForces - 1436D Bandit in a City

https://codeforces.com/problemset/problem/1436/D

這題就是讓村名儘可能集中在葉子上,但是可能葉子上本來就有很多村民,就是這樣。

假設

1. mx[x]為在x點可以抓到的最多的人

2. chal[x]為 在x點還差chal[x]人就可以讓x下面所有葉子都有x個人

大致就是樹形dp的寫法了

具體看程式碼

#include<iostream>
#include<cstring>
#include<algorithm>
#include<queue>
#include<vector>
using namespace std;
const int maxn = 3e5+11;
typedef long long ll;
vector<int>G[maxn];


ll list[maxn];
ll mx[maxn];//最大值 
ll chal[maxn];//缺幾個補上 
ll ans[maxn];
ll cns[maxn];


void add(int x,int y){
	G[x].push_back(y);
}

int dfs(int x,int fa){
	ll siz = 0 ;
	for(int i=0;i<G[x].size();i++){
		int p = G[x][i];
		if(p == fa) continue;
		dfs(p,x);
		cns[x] += cns[p];
		siz++;
		
		mx[x] = max(mx[x],mx[p]);//最大值
		chal[x] += chal[p];           
	}
	if(siz == 0){
		
		mx[x] = list[x]; 
		cns[x] = 1;
		return 0;
	}
	siz = cns[x];
	
	for(int i=0;i<G[x].size();i++){
		int  p = G[x][i];
		if(p == fa) continue;
		chal[x] += (mx[x] - mx[p])*cns[p];
	}
	
	if(list[x] > chal[x]){
		list[x] -= chal[x];
		chal[x] = 0;
		mx[x] += list[x] / siz;
		if(list[x] % siz != 0){
			mx[x] ++;
			chal[x] = siz - list[x] % siz;
		}
		list[x] = 0;
	}
	else{
		chal[x] -= list[x];
		list[x] = 0;
	}
	return 0;
}

int main(){
	int n;
	cin>>n;
	int x,y;
	for(int i=2;i<=n;i++){
		cin>>x;
		add(x,i);
		add(i,x);
	}
	for(int i=1;i<=n;i++){
		cin>>list[i];
	}
	dfs(1,-1);
	cout<<mx[1]<<endl;
	
	return 0;
}