zoukankan      html  css  js  c++  java
  • P3379 【模板】最近公共祖先(LCA)

    题目描述

    如题,给定一棵有根多叉树,请求出指定两个点直接最近的公共祖先。

    输入输出格式

    输入格式:

     

    第一行包含三个正整数N、M、S,分别表示树的结点个数、询问的个数和树根结点的序号。

    接下来N-1行每行包含两个正整数x、y,表示x结点和y结点之间有一条直接连接的边(数据保证可以构成树)。

    接下来M行每行包含两个正整数a、b,表示询问a结点和b结点的最近公共祖先。

     

    输出格式:

     

    输出包含M行,每行包含一个正整数,依次为每一个询问的结果。

    输入输出样例

    输入样例#1: 复制
    5 5 4
    3 1
    2 4
    5 1
    1 4
    2 4
    3 2
    3 5
    1 2
    4 5
    输出样例#1: 复制
    4
    4
    1
    4
    4
    

    说明

    时空限制:1000ms,128M

    数据规模:

    对于30%的数据:N<=10,M<=10

    对于70%的数据:N<=10000,M<=10000

    对于100%的数据:N<=500000,M<=500000

    样例说明:

    该树结构如下:

    第一次询问:2、4的最近公共祖先,故为4。

    第二次询问:3、2的最近公共祖先,故为4。

    第三次询问:3、5的最近公共祖先,故为1。

    第四次询问:1、2的最近公共祖先,故为4。

    第五次询问:4、5的最近公共祖先,故为4。

    故输出依次为4、4、1、4、4。

    哈哈哈哈哈哈

    放一天多的假

    哈哈哈哈哈

    那我当然要嘚瑟嘚瑟啦

    哈哈哈哈哈哈

    代码:

    #include<iostream>
    #include<cstdio>
    #include<cmath>
    #include<algorithm>
    #include<cstring>
    using namespace std;
    const int N=5e5+7;
    
    int n,Enum,m,s;
    int front[N],fat[N][20],deep[N];
    
    struct node
    {
        int v,nxt;
    } e[N<<1];
    
    int qread()
    {
        int x=0;
        char ch=getchar();
        while(ch<'0' || ch>'9') ch=getchar();
        while(ch>='0' && ch<='9')
        {
            x=x*10+ch-'0';
            ch=getchar();
        }
        return x;
    }
    
    void Insert(int u,int v)
    {
        e[++Enum].v=v;
        e[Enum].nxt=front[u];
        front[u]=Enum;
    }
    
    void dfs(int x)
    {
        int v;
        for(int i=front[x]; i; i=e[i].nxt)
        {
            v=e[i].v;
            if(v==fat[x][0]) continue;
            fat[v][0]=x;
            deep[v]=deep[x]+1;
            dfs(v);
        }
    }
    
    void find_father()
    {
        for(int j=1; j<=19; j++)
            for(int i=1; i<=n; i++)
                fat[i][j]=fat[fat[i][j-1]][j-1];
    }
    
    int Lca(int a,int b)
    {
        if(deep[a]<deep[b]) swap(a,b);
        int tmp=deep[a]-deep[b];
        for(int i=0; i<=19; i++)
            if(tmp&(1<<i))
                a=fat[a][i];
        if(a==b) return a;
        for(int i=19; i>=0; i--)
            if(fat[a][i]!=fat[b][i])
            {
                a=fat[a][i];
                b=fat[b][i];
            }
        return fat[a][0];
    }
    
    int main()
    {
        scanf("%d%d%d",&n,&m,&s);
        int u,v;
        for(int i=1; i<=n-1; i++)
        {
            u=qread();
            v=qread();
            Insert(u,v);
            Insert(v,u);
        }
        dfs(s);
        find_father();
        for(int i=1; i<=m; i++)
        {
            u=qread();
            v=qread();
            printf("%d
    ",Lca(u,v));
        }
        return 0;
    }

    如果你不开心,那我就把右边这个帅傻子分享给你吧,  

    你看,他这么好看,那么深情的望着你,你还伤心吗?  

    真的!这照片盯上他五秒钟就想笑了。  

    一切都会过去的。

  • 相关阅读:
    15-07-23 HTML--标签
    15-07-22 数据库--存储过程、触发器
    15-07-19数据库练习题答案
    15-07-17 数据库练习题
    15-07-20 数据库--索引视图编程
    15-07-17 数据库--高级查询
    c#语句
    SQL 触发器
    SQL 存储过程
    SQL 循环语句
  • 原文地址:https://www.cnblogs.com/Mary-Sue/p/9474539.html
Copyright © 2011-2022 走看看