zoukankan      html  css  js  c++  java
  • 树上倍增法,LCA——CF-832-D

    题目链接

    题目含义

    求树上两个点到第三个点重合路径的最大长度

    题目分析

    设三个点为A,B,C

    dis(A,B)=deep[a]+deep[b]-2*deep[lca(A,B)]

    所以这是个求最近公共祖宗的题

    那么答案可以由两种方法求

    (1)若以C为第三个点,求( dis(a,c)+dis(b,c)-dis(a,b) )/2 然后三个点分别三种情况求最大

    (2)求出三个点两两的公共祖先,取深度最大的点,然后求这点到三个点的最长距离

    题目代码

    #include<stdio.h>
    #include<iostream>
    #include<string.h>
    using namespace std;
    const int maxn=1e5+7;
    int n,q,a,b,c,tot;
    int head[maxn],father[maxn][20],deep[maxn];
    struct node{
        int to,next;
    }edge[maxn*2];
    void add(int u,int v){
        edge[tot].to=v;
        edge[tot].next=head[u];
        head[u]=tot++;
    }
    void dfs(int u,int fa,int d){
        deep[u]=d;
        for(int i=head[u];i!=-1;i=edge[i].next){
            int to=edge[i].to;
            if(to==fa)continue;
            dfs(to,u,d+1);
            father[to][0]=u;
        }
    }
    void InitICA(){
        for(int j=1;j<20;j++)
        for(int i=1;i<=n;i++){
            father[i][j]=father[father[i][j-1]][j-1];
        }
    }
    int lca(int x,int y){
        if(deep[x]<deep[y])swap(x,y);
        for(int i=19;i>=0;i--){
            if(deep[father[x][i]]>=deep[y])x=father[x][i];
        }
        if(x==y)return x;
        for(int i=19;i>=0;i--){
            if(father[x][i]!=father[y][i]){
                x=father[x][i];
                y=father[y][i];
            }
        }
        return father[x][0];
    }
    int dis(int x,int y){
        return deep[x]+deep[y]-2*deep[lca(x,y)];
    }
    int main(){
        scanf("%d%d",&n,&q);
        memset(head,-1,sizeof(head));
        tot=0;
        for(int i=2;i<=n;i++){
            scanf("%d",&a);
            add(a,i),add(i,a);
        }
        dfs(1,0,0);
        InitICA();
        while(q--){
            scanf("%d%d%d",&a,&b,&c);
            int ans=0;
            ans=max(ans,(dis(a,c)+dis(b,c)-dis(a,b))/2);
            ans=max(ans,(dis(a,b)+dis(b,c)-dis(a,c))/2);
            ans=max(ans,(dis(a,c)+dis(a,b)-dis(b,c))/2);
            printf("%d
    ",ans+1);
        }
        return 0;
    }
    View Code

    我是用的第一种方法

    第二种可以看这位博主写的

    链接

  • 相关阅读:
    文件包含漏洞
    任意文件上传
    改变弱口令威胁,从意识开始
    Node.js学习笔记10--Express搭网站(2)
    Node.js学习笔记9——Express框架
    Node.js学习笔记8
    Node.js学习笔记7-文件系统
    node.js学习笔记6
    node.js学习笔记5——核心模块1
    Node.js学习4
  • 原文地址:https://www.cnblogs.com/helman/p/11272997.html
Copyright © 2011-2022 走看看