zoukankan      html  css  js  c++  java
  • 在线查询树上最近公共祖先模板

    在线查询树上最近公共祖先

    标准题目

    第一行有2个整数n和q:n代表树的结点数量,q代表询问的次数接下来n-1行每行两个整数u和v,表示结点u到结点v有一条边。
    然后给出q组询问,每组询问由两个整数a和b构成,询问节点a和b的最近公共祖先。

    样例数据

    input
    8 3
    1 3
    1 2
    3 4
    3 5
    3 6
    2 7
    2 8
    4 5
    6 7
    5 8

    output:
    3
    1
    1

    代码

    1. 邻接表建图

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <cstring>
     4 #include <algorithm>
     5 #include <queue>
     6 using namespace std;
     7 const int lim=100000000;
     8 const int maxn=600010;
     9 struct point {
    10     int to;
    11     int nxt;
    12 } edge[maxn*2];
    13 int n,Q,tot=0;
    14 int dep[maxn]= {0},f[20][maxn];
    15 bool vis[maxn];
    16 int head[maxn];
    17 
    18 void add(int u,int v) {
    19     tot++;
    20     edge[tot].to=v;
    21     edge[tot].nxt=head[u];
    22     head[u]=tot;
    23 }
    24 
    25 
    26 int Lca(int x,int y) { //lca
    27     int temp,co=0,lca;
    28     int tx=x,ty=y;
    29     if(dep[tx]>dep[ty]) swap(tx,ty);
    30     temp=dep[ty]-dep[tx];
    31     while(temp) {
    32         if(temp&1) ty=f[co][ty];
    33         temp>>=1;
    34         co++;
    35     }
    36     if(tx==ty) return tx;
    37     else {
    38         for(int j=19; j+1; j--) {
    39             if((1<<j)>dep[tx]) continue;
    40             if(f[j][tx]!=f[j][ty]) {
    41                 tx=f[j][tx];
    42                 ty=f[j][ty];
    43             }
    44         }
    45         lca=f[0][tx];
    46     }
    47     return lca;
    48 }
    49 inline void bfs() {
    50     queue<int> q;
    51     vis[1]=1;
    52     dep[1]=0;
    53     q.push(1);
    54     while(!q.empty()) { //宽搜处理dep和f[0][i] (父节点)
    55         int tt=q.front();
    56         q.pop();
    57         for(int i=head[tt]; i; i=edge[i].nxt) {
    58             int v=edge[i].to;
    59             if(!vis[v]) {
    60                 vis[v]=1;
    61                 q.push(v);
    62                 dep[v]=dep[tt]+1;
    63                 f[0][v]=tt;
    64             }
    65         }
    66     }
    67 }
    68 int main() {
    69     memset(head,0,sizeof(head));
    70     cin>>n>>Q;
    71     for(int i=1; i<=n-1; i++) {
    72         int a,b;
    73         cin>>a>>b;
    74         add(a,b);//双向建图
    75         add(b,a);
    76     }
    77 
    78     bfs();
    79     for(int j=1; j<20; j++) //倍增
    80         for(int i=1; i<=n; i++)
    81             if(dep[i]>=(1<<j))
    82                 f[j][i]=f[j-1][f[j-1][i]];
    83     while(Q--) {
    84         int a,b,lca;
    85         cin>>a>>b;
    86         lca=Lca(a,b);
    87         cout<<lca<<endl;
    88     }
    89 
    90     return 0;
    91 }

    2. Vector建图

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <queue>
    using namespace std;
    const int maxn=600010;
    
    int n,Q,tot=0;
    int depth[maxn]= {0},f[20][maxn];
    bool vis[maxn];
    int head[maxn];
    vector<int> edge[maxn];
    
    void add(int u,int v) {
        edge[u].push_back(v);
    }
    
    
    int Lca(int x,int y) { //lca
        int temp,co=0,lca;
        int tx=x,ty=y;
        if(depth[tx]>depth[ty]) swap(tx,ty);
        temp=depth[ty]-depth[tx];
        while(temp) {
            if(temp&1) ty=f[co][ty];
            temp>>=1;
            co++;
        }
        if(tx==ty) return tx;
        else {
            for(int j=19; j+1; j--) {
                if((1<<j)>depth[tx]) continue;
                if(f[j][tx]!=f[j][ty]) {
                    tx=f[j][tx];
                    ty=f[j][ty];
                }
            }
            lca=f[0][tx];
        }
        return lca;
    }
    inline void bfs() {
        queue<int> q;
        vis[1]=1;
        depth[1]=0;
        q.push(1);
        while(!q.empty()) { //宽搜处理depth和f[0][i] 
            int now=q.front();
            q.pop();
            int len=edge[now].size();
            for(int i=0; i<len; i++) {
                int v=edge[now][i];
                if(!vis[v]) {
                    vis[v]=1;
                    q.push(v);
                    depth[v]=depth[now]+1;
                    f[0][v]=now;
                }
            }
        }
    }
    int main() {
        memset(head,0,sizeof(head));
        cin>>n>>Q;
        for(int i=1; i<=n-1; i++) {
            int a,b;
            cin>>a>>b;
            add(a,b);//双向建图
            add(b,a);
        }
    
        bfs();
        for(int j=1; j<20; j++) //倍增
            for(int i=1; i<=n; i++)
                if(depth[i]>=(1<<j))
                    f[j][i]=f[j-1][f[j-1][i]];
        while(Q--) {
            int a,b,lca;
            cin>>a>>b;
            lca=Lca(a,b);
            cout<<lca<<endl;
        }
    
        return 0;
    }
  • 相关阅读:
    MyEclipse连接Oracle,出现ORA00604和ORA12705异常
    MyEclipse连接Oracle,出现ORA00604和ORA12705异常
    SSH Secure Shell Client 乱码问题
    android开发(20) 使用adb建立pc和android设备之间的连接。usb连接方式。
    android开发(22)使用正则表达式 。从一个字符串中找出数字,多次匹配。
    .net 中,使用c# 语言 ,执行exe程序。
    [转载]大数据存取的选择:行存储还是列存储?
    android开发(21)蜂鸣提示音和震动提示的实现。
    arcgis for android 学习 (8) 空间查询 点击某点,选中该点所在单位区域。
    android开发(24)使用SQLiteOpenHelper的onUpgrade实现数据库版本升级
  • 原文地址:https://www.cnblogs.com/YQAccelerator/p/7225807.html
Copyright © 2011-2022 走看看