zoukankan      html  css  js  c++  java
  • 【模板】最近公共祖先(LCA)

    Description

    给你一棵有根树,1为根节点,要求你计算出指定两个结点的最近公共祖先。

    Input

    输入文件的第一行两个整数n和m,n为结点个数(2<=n,m<=100,000),结点编号为1到n,m表示询问次数。
    接下来n-1行,每行两个整数x,y,表示x和y之间有一条边相连;
    接下来m行,每行两个整数a和b,要求计算出结点a和b的最近公共祖先。

    Output

    输出文件共m行,每行为一个询问的最近公共祖先的编号。

    Sample Input

    5 2
    1 2
    2 3
    2 4
    5 4
    2 5
    3 5

    Sample Output

    2
    2


    思路

    • 树上倍增求LCA模板

    代码

    #include <iostream>
    #include <cstdio>
    #include <cmath>
    #define maxn 100005
    using namespace std;
    int n,m,cnt,head[maxn],fa[maxn][17],deep[maxn];
    struct node{int next,to;}e[maxn<<1];
    void addedge(int x,int y){e[++cnt].to=y; e[cnt].next=head[x]; head[x]=cnt;}
    void dfs(int u,int pre)
    {
    	fa[u][0]=pre; deep[u]=deep[pre]+1;
    	for(int i=head[u];i;i=e[i].next)
    	{
    		int v=e[i].to;
    		if(v!=pre) dfs(v,u);
    	}
    }
    void st()
    {
    	for(int i=1;i<=log2(n);++i)
    		for(int j=1;j<=n;++j)
    			fa[j][i]=fa[fa[j][i-1]][i-1];
    }
    int lca(int u,int v)
    {
    	if(deep[u]<deep[v]) swap(u,v);
    	while(deep[u]>deep[v]) u=fa[u][(int)log2(deep[u]-deep[v])];
    	if(u==v) return u;
    	for(int i=log2(n);i>=0;--i)
    	    if(fa[u][i]!=fa[v][i]) u=fa[u][i],v=fa[v][i];
    	return fa[u][0];
    }
    int main()
    {
    	scanf("%d%d",&n,&m);
    	for(int i=1,u,v;i<n;++i) scanf("%d%d",&u,&v),addedge(u,v),addedge(v,u);
    	dfs(1,0); st();
    	while(m--)
    	{
    		int u,v; scanf("%d%d",&u,&v);
    		printf("%d
    ",lca(u,v));
    	}
    	return 0;
    }
    
  • 相关阅读:
    vue中点击输入框弹出事件
    shiro
    Java转Kotlin
    RxJava2详细攻略(四)
    RxJava2详细攻略(三)
    RxJava2详细攻略(二)
    RxJava2详细攻略(一)
    DataBinding使用介绍
    类集框架
    使用CrashHandler获取应用crash信息
  • 原文地址:https://www.cnblogs.com/wuwendongxi/p/13516326.html
Copyright © 2011-2022 走看看