zoukankan      html  css  js  c++  java
  • 蒜头君的树

    蒜头君的树

    2017-09-07


    题目描述

    蒜头君有一棵有根树,树的每一边都有边权,蒜头君想知道任意两点间最短距离之和为多少。另外,由于各种原因,蒜头君的树的边的边权会发生若干次改变,蒜头君想让你告诉他,每一次改变后,任意两点间最短距离之和为多少?


    输入格式

    第一行一个正整数 nn,表示蒜头君的树上的结点个数。

    接下来 n-1n1 行,每行两个正整数 x_i,y_ixi​​,yi​​,x_ixi​​表示 i+1i+1 号结点的父亲结点的编号,保证其父结点编号小于自己编号。y_iyi​​ 表示 i+1i+1 号结点的父亲结点与自己间边的距离。

    接下来一行一个整数 mm,表示树的边权发生改变的次数。

    接下来 mm 行,每行两个正整数 a,ba,b,表示将 aa结点与其父亲结点之间的距离改为 bb,保证 a ge 2a2。


    输出格式

    先输出一个整数,表示对于原始的树任意两点间最短距离之和。

    接下来 mm 行,每行输出一个整数,表示每一次改变后,任意两点间最短距离之和。


    数据规模


    样例输入

    4
    1 1
    1 1
    1 1
    1
    2 2

    样例输出

    9
    12

    一道裸的dfs的题,不要看到树就害怕,当时模拟这个题的时候我看到树,一想就不会,现在看来,一条边的贡献就是左边点数*右边点数*w
    只要单dfs一边找到一条边的孩子有多少就可以知道右边有多少....水题
    #include<cstdlib>
    #include<cstdio>
    #include<iostream>
    #include<algorithm>
    #define ll long long 
    const ll maxn=100000+9999;
    using namespace std;
    ll read(){
        ll an=0,f=1;char ch=getchar();
        while(!('0'<=ch&&ch<='9')){if(ch=='-')f=-f;ch=getchar();}
        while('0'<=ch&&ch<='9'){an=an*10+ch-'0';ch=getchar();}
        return an*f;
    }
    ll f[maxn],w[maxn<<1],cnt,vis[maxn],size[maxn],n,m;
    ll ans;
    struct saber{
    ll nex,to;
    }b[maxn<<1];
    void add(ll x,ll y,ll wi){
        cnt++;
        b[cnt].nex=f[x];
        b[cnt].to=y;
        w[cnt]=wi;
        f[x]=cnt;
    }
    void dfs(ll x){
        vis[x]=1;size[x]=1;
        for(ll i=f[x];i;i=b[i].nex){
            ll v=b[i].to;
            if(!vis[v]){
                vis[v]=1;
                dfs(v);
                size[x]+=size[v];
            }
        }
    }
    int main(){
        n=read();
        for(ll i=2;i<=n;i++){
            ll x,y;x=read();y=read();
            add(x,i,y);
        }
        dfs(1);
        m=read();
        for(ll i=1;i<n;i++){
            ans+=w[i]*(n-size[b[i].to])*(size[b[i].to]);
        }
        cout<<ans<<endl;
        while(m){m--;
        ll x,y,z;x=read();y=read();
            z=w[x-1];    w[x-1]=y;
            y=y-z;
            ans+=y*(n-size[b[x-1].to])*size[b[x-1].to];
            cout<<ans<<endl;
        }
        return 0;
    }
    s_a_b_e_r
    
    

    注意数据会炸int,全部用ll。。。

  • 相关阅读:
    在下拉框中选择数据
    代码添加批处理类
    重置用户状态(初始化用户)
    当前窗口控制(显示、隐藏、破坏)
    窗体分隔符实现
    使用USB移动硬盘 遭遇 "Windows无法为Volume加载安装程序。请于硬件供应商联系,寻求协助" 错误,“灰鸽子”后遗症的处理
    使用IDL创建TypeLib(.tlb)文件
    ngrep使用方法
    常用的正则表达式
    治疗鼻炎的药
  • 原文地址:https://www.cnblogs.com/ck666/p/7489762.html
Copyright © 2011-2022 走看看