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

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

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

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

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

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

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

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

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

#include 
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> 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);
	}
}

你可能感兴趣的:(CF1900)