zoukankan      html  css  js  c++  java
  • [CF832D] Misha, Grisha and Underground

    有一棵 (n) 个节点的树,一共 (q) 次询问,每次询问给定 (3) 个点,求两条起点终点在这三个点上且不完全重合的路径的最多公共节点数。

    Solution

    枚举公共点,答案为 ((dis(a,b) + dis(a,c) - dis(b,c)) / 2 + 1)

    #include <bits/stdc++.h>
    using namespace std;
    
    #define int long long
    const int N = 1000005;
    
    int n,q,t1,t2,t3;
    vector <int> g[N];
    int dep[N],fa[N][20],vis[N];
    
    void dfs(int p) {
        vis[p]=1;
        for(int q:g[p]) {
            if(vis[q]) continue;
            dep[q]=dep[p]+1;
            fa[q][0]=p;
            dfs(q);
        }
    }
    
    int lca(int p,int q) {
        if(dep[p]<dep[q]) swap(p,q);
        for(int i=18;i>=0;--i) if(dep[fa[p][i]]>=dep[q]) p=fa[p][i];
        for(int i=18;i>=0;--i) if(fa[p][i]-fa[q][i]) p=fa[p][i], q=fa[q][i];
        if(p-q) return fa[p][0];
        return p;
    }
    
    int dist(int p,int q) {
        int l=lca(p,q);
        return dep[p]+dep[q]-2*dep[l];
    }
    
    int calc(int a,int b,int c) {
        return (dist(a,b)+dist(a,c)-dist(b,c))/2;
    }
    
    signed main() {
        ios::sync_with_stdio(false);
        cin>>n>>q;
        for(int i=1;i<n;i++) {
            cin>>t1;
            g[i+1].push_back(t1);
            g[t1].push_back(i+1);
        }
        dep[1]=1;
        dfs(1);
        for(int i=1;i<=18;i++) {
            for(int j=1;j<=n;j++) {
                fa[j][i]=fa[fa[j][i-1]][i-1];
            }
        }
        for(int i=1;i<=q;i++) {
            cin>>t1>>t2>>t3;
            cout<<max(max(calc(t1,t2,t3),calc(t2,t3,t1)),calc(t3,t1,t2))+1<<endl;
        }
    }
    
    
  • 相关阅读:
    套接字的工作流程
    信安系统设计基础(个人报告阅读说明)
    1.1Linux 系统简介(学习过程)
    1.12Linux下软件安装(学习过程)
    作业3.5
    作业1
    变量与基本数据类型
    python入门
    计算机基础知识补充
    计算机基础
  • 原文地址:https://www.cnblogs.com/mollnn/p/12588947.html
Copyright © 2011-2022 走看看