zoukankan      html  css  js  c++  java
  • Codeforces 379F New Year Tree 树的直径的性质推理

    New Year Tree

    我们假设当前的直径两端为A, B, 那么现在加入v的两个儿子x, y。

    求直径的话我们可以第一次dfs找到最远点这个点必定为直径上的点, 然而用这个点第二次dfs找到最远点, 这两个点就是直径。

    因为A, B现在是直径的两端, 那么从v点dfs找到的最远点必定为A或者B, 那么从 x dfs找到的最远点也必定为A或者B, 那么如果有

    新的直径其中一个端点不会变, 当前图和原图的差别就是x和y, 那么比较dist(A, x), dist(B, x)和未加入前直径的长度就能得到当前的直径。

    #include<bits/stdc++.h>
    #define LL long long
    #define fi first
    #define se second
    #define mk make_pair
    #define PLL pair<LL, LL>
    #define PLI pair<LL, int>
    #define PII pair<int, int>
    #define SZ(x) ((int)x.size())
    #define ull unsigned long long
    using namespace std;
    
    const int N = 1e6 + 7;
    const int inf = 0x3f3f3f3f;
    const LL INF = 0x3f3f3f3f3f3f3f3f;
    const int mod = 1e9 + 7;
    const double eps = 1e-8;
    
    int f[N][20], depth[N];
    int q;
    
    int getLca(int u, int v) {
        if(depth[u] < depth[v]) swap(u, v);
        for(int i = 19; i >= 0; i--)
            if(depth[f[u][i]] >= depth[v])
                u = f[u][i];
        if(u == v) return u;
        for(int i = 19; i >= 0; i--)
            if(f[u][i] != f[v][i])
                u = f[u][i], v = f[v][i];
        return f[u][0];
    }
    
    int dist(int u, int v) {
        int lca = getLca(u, v);
        return depth[u] + depth[v] - 2 * depth[lca];
    }
    
    int main() {
        depth[1] = 1;
        depth[2] = depth[3] = depth[4] = 2;
        f[2][0] = f[3][0] = f[4][0] = 1;
        int A = 2, B = 3, dia = 2, n = 4;
        scanf("%d", &q);
        while(q--) {
            int v; scanf("%d", &v);
            depth[n + 1] = depth[v] + 1;
            depth[n + 2] = depth[v] + 1;
            f[n + 1][0] = f[n + 2][0] = v;
            for(int i = 1; i < 20; i++) {
                f[n + 1][i] = f[f[n + 1][i - 1]][i - 1];
                f[n + 2][i] = f[f[n + 2][i - 1]][i - 1];
            }
            int d1 = dist(A, n + 1);
            int d2 = dist(B, n + 1);
            if(d1 > dia) dia = d1, B = n + 1;
            else if(d2 > dia) dia = d2, A = n + 1;
            printf("%d
    ", dia);
            n += 2;
        }
        return 0;
    }
    
    /*
    */
  • 相关阅读:
    第一部分 Linux的规划与安装
    第二部分 Linux 文件、目录与磁盘格式
    for in 遍历对象
    时间
    javaScript模块化
    Hbuilder将移动app或者web项目打包
    echarts的通用属性的介绍
    echart的x轴或y轴区间标签如何从大到小排列
    数组的sort()排序
    解决vscode下载很慢的问题
  • 原文地址:https://www.cnblogs.com/CJLHY/p/10400213.html
Copyright © 2011-2022 走看看