D. New Year Santa Network(组合,预处理)

思路很接近了,但还是糊涂了一下下┭┮﹏┭┮

d f s 直接dfs预处理每条边被计算多少次

, ? 对于一条边,什么情况会经过它?

2 , 1 在这条边的上面选2个点,下面选1个点

1 , 2 在这条边上面选1个点,下面选2个点

2 , 2 每种组合方式都会经过2次这条边,所以乘个2

C n 3 , 总共有C_{n}^{3}种选法,除一下就是初始期望

, , 然后修改每条边,由于知道了这条边计算了几次,直接处理即可

#include <bits/stdc++.h>
using namespace std;
const int maxn=2e5+10;
#define int long long
int q,n,deep[maxn],siz[maxn],lca[maxn];
int l[maxn],r[maxn],w[maxn];
double sumn=0;
struct p{
	int to,w,nxt;
}d[maxn]; int head[maxn],cnt=1;
void add(int u,int v,int w){
	d[cnt]=(p){v,w,head[u]},head[u]=cnt++;
}
void dfs(int u,int fa)
{
	siz[u]=1,deep[u]=deep[fa]+1;
	for(int i=head[u];i;i=d[i].nxt)
	{
		int v=d[i].to;
		if( v==fa )	continue;
		dfs(v,u);
		siz[u]+=siz[v];
		int up=n-siz[v],down=siz[v];
		lca[v]=up*down*(down-1)/2+down*up*(up-1)/2;
		lca[v]*=2;
		sumn+=lca[v]*d[i].w;
	}
}
signed main()
{
	cin >> n;
	for(int i=1;i<n;i++)
	{
		cin >> l[i] >> r[i] >> w[i];
		add(l[i],r[i],w[i] ); add(r[i],l[i],w[i] );
	}
	dfs(1,0);
	cin >> q;
	double k=n*(n-1)*(n-2)/6;
	while( q-- )
	{
		int id,s;//把id条边修改为s 
		cin >> id >> s;
		int index;
		if( deep[ l[id] ]>deep[ r[id] ] )	index=l[id];
		else	index=r[id];
		sumn-=( w[id]-s )*lca[ index ];
		w[id]=s;
		printf("%.7lf\n",sumn/k);
	}
}

猜你喜欢

转载自blog.csdn.net/jziwjxjd/article/details/107981186