• 求lca


    lca模板

    也就是求树上两点的最近公共祖先。

    我们采用树上倍增。

    将两点跳至同一高度。

    一起向上跳。

    bfs(或dfs)预处理节点深度及节点的2的几次方的父亲。

    代码:

    #include <cstdio>
    #include <queue>
    #include <cmath>
    
    using namespace std;
    
    typedef long long int ll;
    const int maxn=100005;
    int n,m,s,tot,head[maxn],d[maxn],f[maxn][35],w;
    struct node{
        int to,nxt;
    }t[maxn];
    inline void add(const int x,const int y){
        t[++tot].to=y;t[tot].nxt=head[x];
        head[x]=tot;
    }
    queue<int>q;
    inline void bfs(const int s){
        q.push(s);
        d[s]=1;
        while(q.size()){
            int x=q.front();q.pop();
            for(int i=head[x];i;i=t[i].nxt){
                int y=t[i].to;
                if(d[y])continue;
                d[y]=d[x]+1;
                f[y][0]=x;
                for(int j=1;j<=w;j++){
                    f[y][j]=f[f[y][j-1]][j-1];
                }
                q.push(y);
            }
        }
    }
    inline int lca(int x,int y){
        if(d[y]>d[x])swap(x,y);
        for(int i=w;i>=0;i--){
            if(d[f[x][i]]>=d[y]){
                x=f[x][i];
            }
        }
        if(x==y)return x;
        for(int i=w;i>=0;i--){
            if(f[x][i]!=f[y][i]){
                x=f[x][i];
                y=f[y][i];
            }
        }
        return f[x][0];
    }
    int main(){
        scanf("%d%d%d",&n,&m,&s);
        for(int i=1;i<n;i++){
            int x,y;
            scanf("%d%d",&x,&y);
            add(x,y);
            add(y,x);
        }
        w=(int)(log(n)/log(2))+1;
        bfs(s);
        for(int i=1;i<=m;i++){
            int x,y;
            scanf("%d%d",&x,&y);
            printf("%d
    ",lca(x,y));
        }
        return 0;
    }
  • 相关阅读:
    #与javascript:void(0)的区别
    单选框、复选框、下拉列表
    数据类型后的“?”
    c#中日期的处理
    日期控件html
    javascript获取后台传来的json
    Hashtable语法简介
    Hashtable(哈希表)
    Dictionary 字典
    远程SQL Server连接不上
  • 原文地址:https://www.cnblogs.com/weijianzhen/p/13542440.html
Copyright © 2020-2023  润新知