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
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;
vectorQ[maxn];
void dfs(int u,int fa);
void dff(int u,int fa);
int main(){
	cin>>n;
	for(int aa,bb,i=1;i>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