题目意思,给你一棵树,然后给你N-1条双向边,现在有3个圣诞老人会选树3个点作为放礼物的仓库。用dis(u,v)表示u->v的距离 ,假设建立3个仓库分别为X,Y,Z,那么会花费
dis(X,Y)+dis(X,Z)+dis(Y,Z)的钱,圣诞老人很懒,他们随机的选择3个点,现在需要定义这个花费的期望值,然后由于城市每年都有会修一条路,新的路会变短,现在有个Q个查询
每次修改一条边的路径(一定是变短),问你这个花费期望值是多少,N和Q都是 10^5
#include<iostream>
#include<algorithm>
#include<stdio.h>
#include<string.h>
#include<vector>
#include<map>
using namespace std;
#define NN 100010
#define LL long long
int m1[NN],m2[NN],L[NN];
vector<int>edge[NN];
map< pair<int,int> ,int>mp;
int dp[NN],n;
LL num[NN];
double sum;
int fun(int u,int v)
{
if(u>v)
swap(u,v);
return mp[make_pair(u,v)];
}
int dfs(int u,int fa)
{
dp[u]=1;
int ss=edge[u].size();
for(int i=0;i<ss;i++)
{
int v=edge[u][i];
if(v==fa)
continue;
dp[u]+=dfs(v,u);
}
if(u!=fa)
{
int id=fun(u,fa);
LL tmp=dp[u];
LL tmp1=(LL)n-(LL)dp[u];
num[id]=tmp*tmp1;
}
return dp[u];
}
int main()
{
while(scanf("%d",&n)!=EOF)
{
mp.clear();
for(int i=0;i<=n;i++)
{
edge[i].clear();
}
for(int i=1;i<n;i++)
{
scanf("%d %d %d",&m1[i],&m2[i],&L[i]);
if(m1[i]>m2[i])
swap(m1[i],m2[i]);
mp[ make_pair(m1[i],m2[i]) ]=i;
edge[m1[i]].push_back(m2[i]);
edge[m2[i]].push_back(m1[i]);
}
dfs(1,1);
sum=0.0;
for(int i=1;i<n;i++)
{
double t1=double(num[i]);
double t2=double(L[i]);
sum=sum+t1*t2;
}
double tt=double(n);
tt=tt*(tt-1.0);
int q;
scanf("%d",&q);
while(q--)
{
int id,len;
scanf("%d %d",&id,&len);
sum=sum-L[id]*num[id]*1.0+len*num[id]*1.0;
L[id]=len;
printf("%lf\n",sum*6.0/tt);
}
}
return 0;
}