P6554 Promises I Can't Keep

这是一个非常有趣(not intersting)的题

传送门   https://www.luogu.com.cn/problem/P6554

dp[x] = sigm dp[p] + list[x]*cnt[x]

ans = dp[x] / cnt[x]

利用换根dp枚举一下就好了,转移有点恶心,因为当儿子是叶子的时候,cnt要改变,当父亲是叶子的时候,cnt还有变化

因为实在不会处理叶子当root的情况,所以干脆直接让度数大于1的节点当根了。。。。。

具体看代码吧

#include<iostream>
#include<cstring>
#include<queue>
#include<cstdio>
#include<algorithm>
#include<string>
using namespace std;
const int maxn = 5e5+11;
double list[maxn];
double dp[maxn],cnt[maxn];
int f[maxn];


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

int dfs(int x,int fa){
	int ff = 0;
	dp[x] = 0;
	cnt[x] = 0;
	for(int i=0;i<G[x].size();i++){
		int p = G[x][i];
		if(p == fa) continue;
		dfs(p,x);
		ff++;
		cnt[x] += cnt[p];
		dp[x] += dp[p];
	}
	dp[x] += list[x] * cnt[x];
	
	if(ff == 0) {
		f[x] =1;
		cnt[x] = 1;
		dp[x] = list[x];
		return 0;	
	}
}
int dfs2(int x,int fa){
	for(int i=0;i<G[x].size();i++){
		int p = G[x][i];
		if(p == fa) continue;
		double cns = dp[x] - dp[p] - list[x]*cnt[p];
		
		dp[p] -= list[p]*cnt[p];
		dp[p] += cns;
		
		if(f[x]){
			cnt[p]++;
			if(f[p]) cnt[p]--;
		}
		else{
			if(f[p]) cnt[p] = cnt[x]-1;
			else cnt[p] = cnt[x];
		}
		dp[p] += list[p]*cnt[p];
		
		dfs2(p,x);
	}
	return 0;
}
int de[maxn];

int main(){
	int n;
	scanf("%d",&n);
	for(int i=1;i<n;i++){
		int x,y;
		scanf("%d%d",&x,&y);
		add(x,y);
		add(y,x);
		de[x]++;
		de[y]++;
	}
	
	for(int i=1;i<=n;i++){
		scanf("%lf",&list[i]);
	}
	double ans = -1e17;
	int root = 1;
	for(int i=1;i<=n;i++){
		if(de[i] > 1) {
			root = i;
			break;	
		}
	}
	dfs(root,-1);
	dfs2(root,-1);
	
	for(int i=1;i<=n;i++){
		ans = max(ans,dp[i]/cnt[i]);
	}
	printf("%.4lf
",ans);
	return 0;
}

  

原文地址:https://www.cnblogs.com/lesning/p/13916983.html