【学习笔记】倍增LCA板子

刚学了倍增LCA,留个板子,原理看OIwiki,洛谷,书什么的。

#include <bits/stdc++.h>
using namespace std;
const int maxn=1005;
vector<int> e[maxn];
int n,m;
int p[maxn][21];
int d[maxn];
bool vis[maxn];
void init()
{
	for(int i=1;i<=n;i++) e[i].clear();
	for(int i=1;i<=n;i++) d[i]=0;
	for(int i=1;i<=n;i++) vis[i]=false;
}
void dfs(int now,int pre)
{
	int sz=e[now].size();
	for(int i=0;i<sz;i++){
		int nxt=e[now][i];
		if(nxt==pre) continue;
		d[nxt]=d[now]+1;
		p[nxt][0]=now;
		dfs(nxt,now);
	}
}
void pre()
{
	for(int j=1;(1<<j)<=n;j++){
		for(int i=1;i<=n;i++){
			p[i][j]=p[p[i][j-1]][j-1];
		}
	}
}
int lca(int a,int b)
{
	if(d[a]<d[b]) swap(a,b);
	int L=0;
	while((1<<L)<=d[a]) L++;
	L--;
	for(int i=L;i>=0;i--){
		if(d[a]-(1<<i)>=d[b]) 
			a=p[a][i];
	}
	if(a==b) return a;
	for(int i=L;i>=0;i--){
		if(p[a][i]!=p[b][i])
			a=p[a][i],b=p[b][i];
	}
	return p[a][0];
} 
int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0);
	int kcase=0;
	int t;cin>>t;
	while(t--){
		cin>>n;
		init();
		for(int i=1;i<=n;i++){
			cin>>m;
			for(int j=1;j<=m;j++){
				int num;cin>>num;
				e[i].push_back(num);
				e[num].push_back(i);
				vis[num]=true;
			}
		}
		int root;
		for(int i=1;i<=n;i++) if(!vis[i]){root=i;break;}
		dfs(root,-1);
		pre();
		int q;cin>>q;
		cout<<"Case "<<++kcase<<":\n";
		while(q--){
			int u,v;cin>>u>>v;
			cout<<lca(u,v)<<endl;
		}
	}
} 
©️2020 CSDN 皮肤主题: 数字20 设计师:CSDN官方博客 返回首页