zoukankan      html  css  js  c++  java
  • 树上倍增模板

    //求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;
            }
        }
    }
    
  • 相关阅读:
    创建线程方法
    List 接口
    implements 的用法
    import和export 的使用方法
    js 实现 a == 'juejin' && a == 666 && a == 888
    position的属性运用
    css calc()函数 长度运算
    .net5一分钟入门
    css 如何让大小不同的图片表现一致,同时自适应呢?
    sqlserver isnull(),Count(),sum(),month(getdate()) 的用法
  • 原文地址:https://www.cnblogs.com/ucprer/p/12284672.html
Copyright © 2011-2022 走看看