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。。。

  • 相关阅读:
    改进昨天的电梯电梯问题
    电梯调度
    结对开发四---实现环状二维数组求最大子数组的和
    结对开发五--对一千个数long型的一维数组求最大子数组的和
    结对开发四------求一维无头数组最大子数组的和
    结对开发3--电梯调度问题需求分析
    SQL基础题
    类和对象(课后题)
    再战文件(小甲鱼课后题)python超级入门
    快来集合!python超级入门笔记
  • 原文地址:https://www.cnblogs.com/ck666/p/7489762.html
Copyright © 2011-2022 走看看