树上倍增模板

//求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\n",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;
        }
    }
}
posted @ 2020-02-08 19:46  UCPRER  阅读(143)  评论(0编辑  收藏  举报