zoukankan      html  css  js  c++  java
  • 模板——倍增LCA

    n个节点,m个询问,root为根节点,fa[i][j]表示i的第2j个祖先

    #include<bits/stdc++.h>
    using namespace std;
    const int P=30;
    //vector son[500001];
    //若清楚每条边哪个是父节点那个是子节点,可以用vector,son[i]表示以i为父节点的子节点;
    int n,m,deep[500001],fa[500001][30]={0},root,jump[500005],num=0;
    bool judge[500005]={0};
    struct nob{
    	int sta,ed,jump;
    }a[1000005];
    //邻接表存储边
    void add(int sta,int ed){
    	num++;
    	a[num].sta=sta;
    	a[num].ed=ed;
    	a[num].jump=jump[sta];
    	jump[sta]=num;
    }
    void dfs(int pos){
    	judge[pos]=1;
    	for (int i=jump[pos]; i>0; i=a[i].jump){
    		if (judge[a[i].ed]) continue;
    		deep[a[i].ed]=deep[pos]+1;
    		fa[a[i].ed][0]=pos;
    		dfs(a[i].ed);
    	}
    }
    void beizeng(){
    	for (int i=1; i<P; i++){
    		for (int l=1; l<=n; l++){
    			fa[l][i]=fa[fa[l][i-1]][i-1];
    		}
    	}
    }
    int LCA(int x,int y){
    	if (deep[y]>deep[x])
    	swap(x,y);
    	int s=deep[x]-deep[y];
    	for (int i=0; i<P; i++)
    		if ((1<<i)&s)
    			x=fa[x][i];
    	//将深度转为二进制,用倍增来跳 
    	if (x==y) return x;
    	for (int i=P-1; i>=0; i--){
    		if (fa[x][i]!=fa[y][i]){
    			x=fa[x][i];
    			y=fa[y][i];
    		}
    	}
    	return fa[x][0];
    }
    int main(){
    	scanf("%d%d%d",&n,&m,&root);
    	//若没有说明根节点的话,那么fa[i][0]==0的为根节点 
    	for (int i=1,x,y; i<n; i++){
    		scanf("%d%d",&x,&y);
    		add(x,y);
    		add(y,x);
    	}
    	deep[root]=1;
    	dfs(root);
    	beizeng();
    	for (int i=1,x,y; i<=m; i++){
    		scanf("%d%d",&x,&y);
    		printf("%d
    ",LCA(x,y));
    	}
    	return 0;
    }
    
  • 相关阅读:
    蓝桥杯训练 | 二分和前缀和 | 02
    广西师大数据结构 | 2015年真题 | 02
    广西师大数据结构 | 2014年真题 | 01
    Centos添加开机自启项
    SUSE系统添加开机自启项
    LNMP
    源码编译安装 libiconv-1.14(php依赖)
    lnmp
    centos添加epel源
    系统挂在镜像
  • 原文地址:https://www.cnblogs.com/cain-/p/7711559.html
Copyright © 2011-2022 走看看