• B 蒜头君的树


    时间限制 : - MS   空间限制 : - KB 
    评测说明 : 2s,256m
    问题描述

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

    输入格式

    输出格式

    r

    样例输入

    4
    1 1
    1 1
    1 1
    1
    2 2

    样例输出

    9
    12

    【题目分析】
    算法 1
    每次 O(N2) 查询每两对点的距离,时间复杂度 O(N2M),期望得分 30 分。
    算法 2
    考虑每条边会在答案中被计算几次,假设删除一条边后所得到的连通分量的大小为 a b
    则 这条边会被统计 a*b 次,可以用一遍 DFS 得到每个点及其子节点的总数,然后可以得
    a b,对于每个询问都做一遍 DFS。时间复杂度 O(N M),期望得分 70 分。
    算法 3
    对于任意一条边 i, 设该边长度为 L[i], 连的儿子节点为 x
    size[x]x 为根的子树中节点的总数。 那么 i 号边被公交线路经过的次数为 size[x]*(n-size[x])
    i 号边对答案的贡献为 TotLen+=L[i]* size[x]*(n-size[x])
    对于每个询问,只考虑修改每一条边会变成什么样,则可以 O(1) 处理每一个询问,时间复
    杂度 O(N + M),期望得分 100 分。

    【参考代码】
     1 #include<cstdio>
     2 #include<cctype>  
     3 #define ll long long
     4 #define maxn 100003
     5 using namespace std;
     6 int n, m, tot;
     7 int Last[maxn], Fa[maxn], Size[maxn], Num[maxn];
     8 ll ans;
     9 ll F[maxn];
    10 char buf[1 << 23], *p1 = buf, *p2 = buf, obuf[1 << 23], *O = obuf;
    11 struct node {
    12     int End, Next, Len;
    13 }Edge[maxn << 1];
    14 namespace Ironclad_Programming {
    15     #define R register int
    16     #define For(i, s, n) for (R i = s; i <= n; ++ i)
    17     #define Getch() (p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 1 << 21, stdin), p1 == p2) ? EOF : *p1 ++) 
    18     inline int read() {
    19         int x = 0, f = 1;
    20         char ch = Getch();
    21         while(!isdigit(ch)){if (ch == '-')f = -1; ch = Getch();}
    22         while(isdigit(ch))x = x * 10 + (ch ^ 48), ch = Getch();
    23         return x * f;
    24     }
    25     inline void Add(int x, int y, int z) {
    26         Edge[++ tot].End = y;
    27         Edge[tot].Len = z;
    28         Edge[tot].Next = Last[x];
    29         Last[x] = tot;
    30     }
    31     void ini() {
    32         n = read();
    33         For (i, 2, n) {
    34             int x, y;
    35             x = read(), y = read();
    36             Add(x, i, y);
    37             Add(i, x, y);
    38             Fa[i] = x;
    39             Num[i] = tot;
    40         }
    41     }
    42     namespace solve {
    43         void DFS(int x) {
    44             ++ Size[x];
    45             for (R i = Last[x]; i; i = Edge[i].Next) {
    46                 int y = Edge[i].End;
    47                 if (y ^ Fa[x]) {
    48                     DFS(y);
    49                     ans += 1LL * Edge[i].Len * F[y];
    50                     Size[x] += Size[y];
    51                 }
    52             }
    53             F[x] = 1LL * Size[x] * (n - Size[x]);
    54         }
    55         void Del_Back() {
    56             m = read();
    57             For (i, 1, m) {
    58                 int x, y;
    59                 x = read(), y = read();;
    60                 ans += 1LL * (y - Edge[Num[x]].Len) * F[x];
    61                 Edge[Num[x]].Len = y;
    62                 printf("%lld
    ", ans);
    63             }
    64         }
    65         void executive() {
    66             DFS(1);
    67             printf("%lld
    ", ans);
    68             Del_Back();
    69         }
    70     }
    71     void Main() {
    72         ini();
    73         solve::executive();
    74     }
    75     #undef R
    76     #undef For
    77     #undef Getch
    78 }
    79 int main() {
    80     Ironclad_Programming::Main();
    81     return 0;
    82 }
  • 相关阅读:
    POJ1045 Bode Plot
    POJ1044 Date bugs
    POJ1043 What's In A Name?
    POJ1042 Gone Fishing
    POJ1041 John's trip
    POJ1040 Transportation
    POJ1039 Pipe
    background-size属性
    一些CSS的备忘
    only-child选择器
  • 原文地址:https://www.cnblogs.com/Limbo-To-Heaven/p/11637261.html
Copyright © 2020-2023  润新知