• 树上倍增模板


    //求LCA,k级祖先
    #include <bits/stdc++.h>
    using namespace std;
    const int maxn = 5e5+5;
    const int maxm = 1e6+5;
    int lg[maxn];
    struct edge {
    	int next, v;
    }E[maxm];
    int head[maxn];
    int tot = 0;
    void addedge(int u, int v) {
    	E[++tot].next = head[u];
    	E[tot].v = v;
    	head[u] = tot;
    }
    int dep[maxn];
    int pa[maxn][25];
    void dfs(int u, int father) {
    	dep[u] = dep[father]+1;
    	pa[u][0] = father;
    	for(int i=1;i<=lg[dep[u]];i++){
            pa[u][i]=pa[pa[u][i-1]][i-1];
    	}
    	for (int i = head[u]; i; i = E[i].next) {
    		int v = E[i].v;
    		if (v != father) {
    			dfs(v, u);
    		}
    	}
    }
    int getLca(int u, int v) {
    	if (dep[u] < dep[v]) swap(u, v);
    	for (int j = lg[dep[u]]; j >= 0; j--) {//让u,v到达同一高度
    		if (dep[u] - (1 << j) >= dep[v]) {
    			u = pa[u][j];
    		}
    	}
    	if (u == v) return u;
    	for (int j = lg[dep[u]]; j >= 0; j--) {
    		if (pa[u][j] != pa[v][j]) {
    			u = pa[u][j];
    			v = pa[v][j];
    		}
    	}
    	return pa[u][0];
    }
    int kth(int u,int k){
        for(int i=20;i>=0;i--){
            if(k&(1<<i)) u=pa[u][i];
        }
        return u;
    }
    void init(int n){
        for(int i=2;i<=n;i++){
            lg[i]=lg[i/2]+1;
        }
    }
    int main () {
        init(maxn-5);
        int n,m,s;
        scanf("%d%d%d",&n,&m,&s);
        for(int i=1;i<=n-1;i++){
            int u,v;
            scanf("%d%d",&u,&v);
            addedge(u,v);
            addedge(v,u);
        }
        dfs(s,0);
        for(int i=1;i<=m;i++){
            int u,v;
            scanf("%d%d",&u,&v);
            printf("%d
    ",getLca(u,v));
        }
    }
    
    //求两点间路径上的最小权值
    const int INF=1e9;
    namespace lca{
        int lg[maxn];
        struct edge {
            int next, v, w;
        }E[maxn];
        int head[maxn];
        int tot = 0;
        void addedge(int u, int v, int w) {
            E[++tot].next = head[u];
            E[tot].v = v;
            E[tot].w = w;
            head[u] = tot;
        }
        int dep[maxn];
        int pa[maxn][25];
        int mn[maxn][25];
        void dfs(int u, int father, int w) {
            dep[u] = dep[father]+1;
            pa[u][0] = father;
            mn[u][0] = w;
            for(int i=1;i<=lg[dep[u]];i++){
                pa[u][i]=pa[pa[u][i-1]][i-1];
                mn[u][i]=min(mn[u][i-1],mn[pa[u][i-1]][i-1]);
            }
            for (int i = head[u]; i; i = E[i].next) {
                int v = E[i].v, w = E[i].w;
                if (v != father) {
                    dfs(v, u, w);
                }
            }
        }
        int getMin(int u, int v) {
            if (dep[u] < dep[v]) swap(u, v);
            int ans=INF;
            for (int j = lg[dep[u]]; j >= 0; j--) {//让u,v到达同一高度
                if (dep[u] - (1 << j) >= dep[v]) {
                    ans = min(ans,mn[u][j]);
                    u = pa[u][j];
                }
            }
            if (u == v) return ans;
            for (int j = lg[dep[u]]; j >= 0; j--) {
                if (pa[u][j] != pa[v][j]) {
                    ans=min(ans,mn[u][j]);
                    ans=min(ans,mn[v][j]);
                    u = pa[u][j];
                    v = pa[v][j];
                }
            }
            ans=min(ans,mn[u][0]);
            ans=min(ans,mn[v][0]);
            return ans;
        }
        void init(){
            for(int i=1;i<=maxn-5;i++){
                for(int j=0;j<=24;j++)mn[i][j]=INF;
            }
            for(int i=2;i<=maxn-5;i++){
                lg[i]=lg[i/2]+1;
            }
        }
    }
    
  • 相关阅读:
    php 给图片添加文字水印 可控制位置,旋转,多行文字
    太多的用户请求,网站出现了504
    这些问题,你注意了吗?
    ubuntu 系统环境配置记录
    node.js开发指南中出现的问题 has no method 'router'解决办法
    在nodejs express 中使用session的功能
    更改窗口大小,重新加载微博发布框
    原生js控制audio标签自动播放
    利用css3转换transform画五星红旗
    css3+js旗帜飘动
  • 原文地址:https://www.cnblogs.com/ucprer/p/12284672.html
Copyright © 2020-2023  润新知