codeforces New Year Santa Network

题目意思,给你一棵树,然后给你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;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值