1. 程式人生 > 實用技巧 >codeforces 1436D - Bandit in a City (貪心)

codeforces 1436D - Bandit in a City (貪心)

題目連結:https://codeforces.com/problemset/problem/1436/D

對於每個子樹,最好的情況是所有的人都平均分配到每個葉子上,
但有些人是不能往回走的,不過這並不影響答案,因為如果有人過不來,那答案必定比當前節點的 \(sum[u]/lev[u]\)
所以只需要從葉子到根節點統計\(sum[u]/lev[u]\)的最大值即可

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<cmath>
#include<stack>
#include<queue>
using namespace std;
typedef long long ll;

const int maxn = 200100;

int n;
ll ans;
ll a[maxn];

int h[maxn],cnt = 0;
struct E{
	int to,next;
}e[maxn*2];
void add(int u,int v){
	e[++cnt].to = v;
	e[cnt].next = h[u];
	h[u] = cnt;
}

ll lev[maxn];
ll sum[maxn];

void dfs(int u,int par){
	sum[u] = a[u]; lev[u] = 0;
	int cnt = 0;
	for(int i=h[u];i!=-1;i=e[i].next){
		int v = e[i].to;
		if(v == par) continue;
		++cnt;
		dfs(v,u);
		lev[u] += lev[v];
		sum[u] += sum[v];
	}
	if(!cnt) lev[u] = 1ll;
	
	ll tmp;
	if(sum[u] % (1ll * lev[u]) == 0) tmp = (sum[u] / (1ll * lev[u])) ;
	else tmp = (sum[u] / (1ll * lev[u]) + 1);
	ans = max(ans,tmp);
}

ll read(){ ll s=0,f=1; char ch=getchar(); while(ch<'0' || ch>'9'){ if(ch=='-') f=-1; ch=getchar(); } while(ch>='0' && ch<='9'){ s=s*10+ch-'0'; ch=getchar(); } return s*f; }

int main(){
	memset(h,-1,sizeof(h));
	n = read(); int u; ans = 0;
	for(int i=2;i<=n;++i){
		u = read();
		add(u,i), add(i,u);
	}
	
	for(int i=1;i<=n;++i) a[i] = read();

	dfs(1,0);
	
	printf("%lld\n",ans);
	
	return 0;
}