其他分享
首页 > 其他分享> > P6554 Promises I Can't Keep

P6554 Promises I Can't Keep

作者:互联网

首先要把题目分析清楚

假如每个点作为根节点 所有叶节点到该根节点的路径权值和 除以 以该节点为根节点的叶节点个数

这个除以操作很烦 我们想办法先去掉 (一般这种除以什么的都要先乘上 最后再除)

所以我们先不考虑除以这个操作,因为以该节点为根节点的叶节点个数我们单独维护还是很好维护的-->cnt[]数组

这个题很容易想到换根dp

先找到一个一定不是叶节点的点作为根节点 然后遍历一遍整个树 依次考虑将根为另一个点所产生的价值差

假设rt是我们一开始认定的根节点 目前我们位于u点,我们已经算到以他的dp值(就是其他叶节点到他的路径权值和)

to是u的一个儿子

分两种情况

如果to是叶节点 则 将根换做to dp[to]=dp[u]-(val[to]+val[u])+val[to]×(cnt[rt]-1)

如果to不是叶结点 则 dp[to]=dp[u]-cnt[to]×val[u]+(cnt[rt]-cnt[to])×val[to]

最后统计一下ans就好

#include<bits/stdc++.h>
using namespace std;
#define lowbit(x) x&(-x)
#define ll long long
const int maxn=1e5+5; 
int n,rt;
int vis[maxn];
double dp[maxn],val[maxn],cnt[maxn];
double ans=-1e9;
vector<int>Q[maxn];
void dfs(int u,int fa);
void dff(int u,int fa);
int main(){
	cin>>n;
	for(int aa,bb,i=1;i<n;i++)
	cin>>aa>>bb,Q[aa].push_back(bb),Q[bb].push_back(aa);
	for(int i=1;i<=n;i++)cin>>val[i];
	for(int i=1;i<=n;i++)
	if(Q[i].size()!=1){
	rt=i;break;
	} 
	dfs(rt,0); 
	dff(rt,0);
	for(int i=1;i<=n;i++)
	ans=max(ans,dp[i]/(cnt[rt]-vis[i]));
	printf("%.4lf\n",ans);
     return 0;
}
void dfs(int u,int fa){
	for(int i=0;i<Q[u].size();i++){
		int to=Q[u][i];
		if(to==fa)continue;
		dfs(to,u);
		cnt[u]+=cnt[to];
		dp[u]+=dp[to];
    }
    dp[u]+=val[u]*cnt[u];
    if(!cnt[u])dp[u]=val[u],cnt[u]=1,vis[u]=1;
}
void dff(int u,int fa){
	for(int i=0;i<Q[u].size();i++){
		int to=Q[u][i];
		if(to==fa)continue;
		if(vis[to])
		dp[to]=dp[u]-val[u]+val[to]*(cnt[rt]-2);
		else dp[to]=dp[u]-val[u]*cnt[to]+val[to]*(cnt[rt]-cnt[to]);
		dff(to,u);	
	}
}

标签:Promises,val,int,cnt,Keep,P6554,maxn,节点,dp
来源: https://www.cnblogs.com/wzxbeliever/p/16095744.html