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

    蒜头君的树

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

    输入格式

    第一行一个正整数 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

    题解:

    每一条边可以将图分为两个点集,这条边被利用的次数就是两个点集中点数之和,所以每次只需要修改一条边即可。

    代码如下:

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<cmath>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    typedef long long lol;
    lol n,m,ans;
    lol head[100005],size=1;
    struct node{lol next,to,dis;}edge[200005];
    void putin(lol from,lol to,lol dis){size++;edge[size].next=head[from];edge[size].to=to;edge[size].dis=dis;head[from]=size;}
    void in(lol from,lol to,lol dis){putin(from,to,dis);putin(to,from,dis);}
    
    lol fa[100005],cnt[100005],tot,dis[100001];
    void dfs(lol r)
    {
        lol i;
        for(i=head[r];i!=-1;i=edge[i].next)
        {
            lol y=edge[i].to;
            if(y!=fa[r])
            {
                dfs(y);
                cnt[r]+=cnt[y];
                tot+=cnt[y]*(n-cnt[y])*edge[i].dis;
            }
        }
        cnt[r]++;
        return;
    }
    lol gi()
    {
        lol ans=0,f=1;
        char i=getchar();
        while(i<'0'||i>'9'){if(i=='-')f=-1;i=getchar();}
        while(i>='0'&&i<='9'){ans=ans*10+i-'0';i=getchar();}
        return ans*f;
    }
    int main()
    {
        lol i,j;
        memset(head,-1,sizeof(head));
        n=gi();
        for(i=2;i<=n;i++)
        {
            fa[i]=gi();dis[i]=gi();
            in(fa[i],i,dis[i]);
        }
        dfs(1);
        printf("%lld
    ",tot);
        m=gi();
        for(i=1;i<=m;i++)
        {
            lol x=gi(),y=gi();
            tot+=(y-dis[x])*cnt[x]*(n-cnt[x]);
            printf("%lld
    ",tot);
            dis[x]=y;
        }
        return 0;
    }
  • 相关阅读:
    apscheduler 踩坑
    fastapi 导出excel文件
    python flask 使用日志
    git 头指针游离问题
    C# 连接mysql填坑
    前端项目proxy小问题
    需完善--日志框架
    依赖<dependency>的scope了解
    git 退回到指定tag版本
    git切换远程仓库地址
  • 原文地址:https://www.cnblogs.com/huangdalaofighting/p/7257695.html
Copyright © 2011-2022 走看看