首页 > 编程语言 >6th 2022/6/8 算法总结·LCA·倍增

6th 2022/6/8 算法总结·LCA·倍增

时间:2022-09-23 19:59:35浏览次数:44  
标签:binary return int 6th father deep 2022 LCA 500001

开头的话

这个算法对于大部分图论无环图题都是必备的,应多多复习

大概是对于两个点的公共祖先

倍增

众所周知,为了找到公共祖先,最暴力的算法就莫过于一个个往上跳,直至相遇

而倍增,就是一大步一大步跳

首先,设\(F_{i,j}\)

为从第i号店往上跳\(2^j\)步

很好转移吧,就是\(F_{i,j}=F_{F_{i,j-1},j-1}\)

简单的思路,第\(2^j\)

步就是两个\(2^{j-1}\)步

然后一大步一大步跳即可

注意:若跳过头了,就是他们跳到一个地方去了啊

还需在最开始时,把他们弄到同一层去啊

只需化二进制他们深度之差后再把深度大的跳上来啊

树剖

需前置知识树链剖分

树剖打法,就是跑一遍树剖板子,然后你会发现,在跳链时,当他们在同一条链后,深度浅的就是LCA

树剖LCA常数小,且好打得多

推荐

总结

在打这个时,出现了初始化问题

还需注意和复习

代码(展示倍增)

#include<cstdio>
#include<cmath> 
using namespace std;
int n,m,root;
int bz[500001];
int *a[500001],len[500001];
int l[500001],r[500001],x,y,max_deep=1;
int jump_binary[100001],len_binary;
int father[500001],deep[500001],f[500001][21];
int ans;
void swap(int &a,int &b){
	int g=a;a=b;b=g;
}
int max(int x,int y){
	return x>y?x:y;
}
int pow(int x,int y){
	int h=1;
	for(int i=1;i<=y;i++){
		h*=x;
	}
	return h;
}
void build_tree(int x){
	bz[x]=1;
	for(int i=1;i<=a[x][0];i++){
		if(bz[a[x][i]]==1){
			a[x][i]=-1;
			continue;
		}
		build_tree(a[x][i]);
	}
}
void get(int x,int delta,int fath){
	father[x]=fath;
	deep[x]=delta;
	for(int i=1;i<=a[x][0];i++){
		if(a[x][i]==-1){
			continue;
		}
		max_deep=max(max_deep,deep[x]);
		get(a[x][i],delta+1,x);
	}
}
void get_f(int x,int i_f){
	int len_f=pow(2,i_f);
	if(x!=root){
		if(i_f==0){
			f[x][0]=father[x];
		}
		else{
			if(deep[x]>len_f){
				f[x][i_f]=f[f[x][i_f-1]][i_f-1];
			}
		}
	}
	for(int i=1;i<=a[x][0];i++){
		if(a[x][i]==-1){
			continue;
		}
		get_f(a[x][i],i_f);
	}
}
void turn_into_binary(int x){
	while(x>0){
		jump_binary[++len_binary]=x%2;
		x/=2;
	}
}
int get_LCA(int x,int y){
	int distance;
	if(deep[x]!=deep[y]){
		if(deep[x]<deep[y]){
			swap(x,y);
		}
		len_binary=0;
		turn_into_binary(distance);
		for(int i=len_binary;i>=1;i--){
			int now_binary=len_binary-i+1;
			if(jump_binary[now_binary]==1){
				x=f[x][now_binary-1];
			}
		}
	}
	int w=log2(max_deep);
	if(x==y){
		return x;
	}
	if(father[x]==father[y]){
		return father[x];
	}
	while(f[x][w]==0||f[y][w]==0||f[x][w]==f[y][w]||father[f[x][w]]!=father[f[y][w]]){
		if(x==0||y==0){
			return root;
		}
		if(f[x][w]==f[y][w]&&w>0){
			w--;
		}
		else{
			x=f[x][w];
			y=f[y][w];
			if(father[x]==father[y]&&f[x][w]!=f[y][w]){
				return father[x];
			}
		}
	}
	x=f[x][w];
	y=f[y][w];
	return father[x];
}
int main(){
	scanf("%d%d%d",&n,&m,&root);
	for(int i=1;i<n;i++){
		scanf("%d%d",&l[i],&r[i]);
		len[l[i]]++;
		len[r[i]]++;
	}
	for(int i=1;i<=n;i++){
		a[i]=new int[len[i]+1];
		a[i][0]=0;
	}
	for(int i=1;i<n;i++){
		a[l[i]][++a[l[i]][0]]=r[i];
		a[r[i]][++a[r[i]][0]]=l[i];
	}
	build_tree(root);
	get(root,1,-1);
	int log2n=log2(max_deep);
	for(int i=0;i<=log2n;i++){
		get_f(root,i);
	}
	for(int i=1;i<=m;i++){
		scanf("%d%d",&x,&y);
		ans=get_LCA(x,y);
		printf("%d\n",ans);
	}
}

标签:binary,return,int,6th,father,deep,2022,LCA,500001
From: https://www.cnblogs.com/tlz-place/p/16724017.html

相关文章

  • 8th 2022/7/6 模拟赛总结3
    这次打得不算好,因为该拿的分没拿到,如T3题意理解的偏差导致失分,T1找规律欠缺,推导欠缺导致窒息,T2是一道贪心+DP,贪心原来优化最优解的寻找方式T4则是一道字符串题,用最长公......
  • 11th 2022/7/11 模拟赛总结6
    这次可能还行吧,200pts,还进行了核酸,rank7,还凑合这次对于暴力是真的没有耐心,T3T4暴力打炸,全0但是。。。T1T2全A了,还行吧,T2是最小生成树,好久没打了,手推了0.5h,拿到100分,而T1......
  • 10th 2022/7/8 模拟赛总结5
    这次还行,但大家分数相差也并不大,自己是几乎尽全力,(除T4没打暴力以外)嗯,发现了许多提升空间,如DP,虽然能在知道是DP的情况下推出来一点点,但是对DP的应用以及理解还是差了很多,......
  • 9th 2022/7/7 模拟赛总结4
    这次仍然打得不算好,但这次却与上次性质不同了上次是知识面欠缺,而这次却是比赛的策略问题这是比赛,不是做题因为是做题的思维,导致了一场悲剧,即见到自己能打的就开打这一......
  • 12th 2022/7/11 RMQ专题复习
    分为三类吧线段树这种数据结构挺有用的,使用范围是时间,看着办嘛,\(O(n\logn)\)的算法,修改加入查询都是\(O(\logn)\)然后建树\(O(n\logn)\)看着办大概思路就是将一个......
  • 【2022-09-23】DRF入门到入土(一)
    drf入门规范一、web应用模式web应用模式分为两种,一种是前后端不分离,一种是前后端分离前后端不分离前后端分离二、API接口为了在团队内部形成共识、防止......
  • 14th 2022/7/12 模拟赛总结7
    这次总的来说可能还行,rk11,较上次差点,但却是保持住了若是继续保持,将有利于我的雄心再起嗯加油回到比赛,这次先T3,T3轻松推出DP转移方程,然后发现所用的无用状态过多,去世,TL......
  • 15th 2022/7/13 模拟赛总结8
    这次嗯,打得不大好总的来说,是T2正解打挂,然后看见了T3的解决方法却没有深入研究最后T4给了最少的时间然后打完也没有什么事情干,嗯,这种情况可以做出一些改进的方法当然是......
  • 2nd 2022/5/3-2022/5/4 简单数论学习
    Day-1/2:2022/5/3·1最大公约数枚举。。。训算法质因数分解。。。是个办法,但大材小用,浪费了算法得来的其他数据,时间较慢欧几里得算法,辗转相除,巧妙消元,时间$O(\l......
  • 3rd 2022/5/9 题目总结·数论篇·欧拉函数·【SDOI2008】仪仗队
    原题作为体育委员,C君负责这次运动会仪仗队的训练。仪仗队是由学生组成的N*N的方阵,为了保证队伍在行进中整齐划一,C君会跟在仪仗队的生后方,根据其视线所及的学生人数......