ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

论求 $lca$ 最有效的方法是

2022-07-23 11:34:18  阅读:119  来源: 互联网

标签:dep ch fa int 论求 有效 dfn lca inline


目录

    \(standard\_table\) : 欧拉序 + \(ST\) 表

    \(multiplication\) : 倍增

    \(tree_chain_subdivision\) : 树链剖分

    #include<bits/stdc++.h>
    using namespace std;
    
    const int N=5e5+5;
    
    inline int read(){
    	int x=0,f=1;char ch=getchar();
    	while(!isdigit(ch)){if(ch=='-') f=-1;ch=getchar();}
    	while(isdigit(ch)){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
    	return x*f;
    }
    
    int n,m,rt,cnt;
    vector <int> G[N];
    
    namespace standard_table{
    	int dfn[N],dep[N],f[N*2][21];
    	inline void dfs(int x,int fa){
    		dep[x]=dep[fa]+1;
    		dfn[x]=++cnt;
    		f[cnt][0]=x;
    		for(auto y:G[x]){
    			if(y==fa) continue;
    			dfs(y,x);
    			f[++cnt][0]=x;
    		}
    	}
    	inline int lca(int x,int y){
    		int l=dfn[x],r=dfn[y];
    		if(l>r) swap(l,r);
    		int k=log2(r-l+1);
    		if(dep[f[l][k]]<=dep[f[r-(1<<k)+1][k]]) return f[l][k];
    		return f[r-(1<<k)+1][k];
    	}
    	inline void pre_work(){
    		cnt=0;
    		dfs(rt,0);
    		for(int j=1;(1<<j)<=cnt;++j)
    			for(int i=1;i+(1<<j)-1<=cnt;++i)
    				f[i][j]=dep[f[i][j-1]]<dep[f[i+(1<<j-1)][j-1]]?
    					f[i][j-1]:f[i+(1<<j-1)][j-1];
    	}
    	inline void solve(){
    		pre_work();
    		while(m--){
    			int x=read(),y=read();
    			printf("%d\n",lca(x,y));
    		}
    	}
    }
    //standard_table:35 lines
    //time:O(2nlogn+m)
    //space:O(2nlogn)
    namespace multiplication{
    	int dep[N],f[N][20];
    	inline void dfs(int x,int fa){
    		dep[x]=dep[fa]+1,f[x][0]=fa;
    		for(int i=1;i<=19;++i)
    			f[x][i]=f[f[x][i-1]][i-1];
    		for(auto y:G[x])
    			if(y!=fa) dfs(y,x);
    	}
    	inline int lca(int x,int y){
    		if(dep[x]<dep[y]) swap(x,y);
    		for(int i=19;i>=0;--i)
    			if(dep[f[x][i]]>=dep[y])
    				x=f[x][i];
    		if(x==y) return x;
    		for(int i=19;i>=0;--i)
    			if(f[x][i]!=f[y][i])
    				x=f[x][i],y=f[y][i];
    		return f[x][0];
    	}
    	inline void solve(){
    		dfs(rt,0);
    		while(m--){
    			int x=read(),y=read();
    			printf("%d\n",lca(x,y));
    		}
    	}
    }
    //multiplication:28 lines
    //time:O((n+m)logn)
    //space:O(nlogn)
    namespace tree_chain_subdivision{
    	int dep[N],son[N],top[N],dfn[N],sz[N],f[N];
    	inline void dfs1(int x,int fa){
    		dep[x]=dep[fa]+1,sz[x]=1,f[x]=fa;
    		int maxson=-1;
    		for(auto y:G[x]){
    			if(y==fa) continue;
    			dfs1(y,x);
    			sz[x]+=sz[y];
    			if(maxson<sz[y]) son[x]=y,maxson=sz[y];
    		}
    	}
    	inline void dfs2(int x,int tp){
    		top[x]=tp,dfn[x]=++cnt;
    		if(!son[x]) return;
    		dfs2(son[x],tp);
    		for(auto y:G[x])
    			if(y!=f[x]&&y!=son[x])
    				dfs2(y,y);
    	}
    	inline int lca(int x,int y){
    		while(top[x]!=top[y]){
    			if(dep[top[x]]<dep[top[y]]) swap(x,y);
    			x=f[top[x]];
    		}
    		return dep[x]<dep[y]?x:y;
    	}
    	inline void solve(){
    		dfs1(rt,0);
    		dfs2(rt,rt);
    		while(m--){
    			int x=read(),y=read();
    			printf("%d\n",lca(x,y));
    		}
    	}
    }
    //tree_chain_subdivision:36 lines
    //time:O(n+mlogn)
    //space:O(n)
    signed main(){
    	n=read(),m=read(),rt=read();
    	for(int i=1;i<n;++i){
    		int x=read(),y=read();
    		G[x].push_back(y);
    		G[y].push_back(x);
    	}
    	//standard_table::solve();
    	//multiplication::solve();
    	//tree_chain_subdivision::solve();
    }
    

    标签:dep,ch,fa,int,论求,有效,dfn,lca,inline
    来源: https://www.cnblogs.com/into-qwq/p/16511238.html

    本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
    2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
    3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
    4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
    5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

    专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

    Copyright (C)ICode9.com, All Rights Reserved.

    ICode9版权所有