• 祖孙询问


    给定一棵包含 nn 个节点的有根无向树,节点编号互不相同,但不一定是 1∼n。

    有 mm 个询问,每个询问给出了一对节点的编号 x 和 y,询问 x 与 y 的祖孙关系。

    输入格式

    输入第一行包括一个整数 表示节点个数;

    接下来 n 行每行一对整数 a 和 b,表示 a 和 b 之间有一条无向边。如果 b 是 −1,那么 a 就是树的根;

    第 n+2 行是一个整数 m 表示询问个数;

    接下来 m 行,每行两个不同的正整数 x 和 y,表示一个询问。

    输出格式

    对于每一个询问,若 x 是 y 的祖先则输出 1,若 y 是 x 的祖先则输出 2,否则输出 00。

    数据范围

    1≤n,m≤4×10^4
    1≤每个节点的编号≤4×10^4

    输入样例:

    10
    234 -1
    12 234
    13 234
    14 234
    15 234
    16 234
    17 234
    18 234
    19 234
    233 19
    5
    234 233
    233 12
    233 13
    233 15
    233 19
    

    输出样例:

    1
    0
    0
    0
    2
    

    思路

    lca模板题

    代码

    #include<bits/stdc++.h>
    using namespace std;
    const int N=4e4+10;
    int n,root,idx,h[N],q[N],dep[N],anc[N][20];
    struct eg{
        int v,nex;
    }e[N*2];
    void add(int u,int v){
        e[idx]={v,h[u]};
        h[u]=idx++;
    }
    void bfs(){
        int hh=0,tt=0;
        memset(dep,0x3f,sizeof dep);
        q[tt++]=root;
        dep[0]=0;
        dep[root]=1;
        while(hh!=tt){
            int u=q[hh++];
            if(hh==N) hh=0;
            for(int i=h[u];~i;i=e[i].nex){
                int v=e[i].v;
                if(dep[v]>dep[u]+1){
                    dep[v]=dep[u]+1;
                    q[tt++]=v;
                    if(tt==N) tt=0;
                    anc[v][0]=u;
                    for(int j=1;j<=15;++j)
                        anc[v][j]=anc[anc[v][j-1]][j-1];
                    //cout<<v<<" "<<dep[v]<<endl;
                }
            }
        }
    }
    int lca(int u,int v){
        if(dep[u]<dep[v]) swap(u,v);
        for(int i=15;i>=0;--i){
            if(dep[anc[u][i]]>=dep[v])
                u=anc[u][i];
        }
        if(u==v) return u;
        for(int i=15;i>=0;--i){
            if(anc[u][i]!=anc[v][i]){
                u=anc[u][i];
                v=anc[v][i];
            }
        }
        return anc[u][0];
    }
    int main(){
        cin>>n;
        memset(h,-1,sizeof h);idx=0;
        for(int i=1;i<=n;++i){
            int a,b;
            scanf("%d%d",&a,&b);
            if(b==-1) root=a;
            else add(a,b),add(b,a);
        }
        bfs();
        int m;
        cin>>m;
        while(m--){
            int a,b;
            scanf("%d%d",&a,&b);
            int t=lca(a,b);
            if(t==a) cout<<"1\n";
            else if(t==b) cout<<"2\n";
            else cout<<0<<endl;
        }
        return 0;
    }
    
    
  • 相关阅读:
    VS2012 professional和VS2012 Ultimate的区别
    ConcurrentDictionary和Dictionary
    ConcurrentDictionary的ToDictionary
    AutoResetEvent
    查看局域网内某个ip的mac地址
    斗争程序猿(三十八)——历史朝代大学(两)——我与数据库的故事
    Windowsport80解决方案被占用
    unity3d 各功能的运行秩序,打回来,订购,的次数
    蜘蛛爱上你的网站
    Java线(一个):线程安全的和不安全
  • 原文地址:https://www.cnblogs.com/jjl0229/p/12894754.html
Copyright © 2020-2023  润新知