LCA
(LCA)=最近公共祖先。
1.初始化(lg)数组,其代表(lg2+1)。
2.利用倍增的思想去求(fa[u][i]),在(u)点向上走(2^i)步时的祖先是谁。深度(dep)也同时求出。
3.初始化(fa[u][0]=father)
4.(LCA)
int LCA(int x,int y){
if(dep[x]<dep[y])
swap(x,y);
while(dep[x]>dep[y]){
x=fa[x][lg[dep[x]-dep[y]]-1];//一直跳直到深度相同
}
if(x==y)return x;
for(int k=lg[dep[x]]-1;k>=0;--k){
if(fa[x][k]!=fa[y][k])//向上跳从大->小,第一个不相等的点就是公共祖先的儿子
x=fa[x][k],y=fa[y][k];
}
return fa[x][0];
P3379 【模板】最近公共祖先(LCA)
#include<bits/stdc++.h>
using namespace std;
//#define int long long
int n,m,s;
const int maxn=5e5+10;
int head[maxn],tot=0;
struct edge{
int to,next;
}edge[maxn<<1];
void add(int u,int v){
edge[++tot].to=v;
edge[tot].next=head[u];
head[u]=tot;
}
int dep[maxn],fa[maxn][22],lg[maxn];
void dfs(int u,int father){
dep[u]=dep[father]+1;
fa[u][0]=father;
for(int i=1;i<=lg[dep[u]];++i){
fa[u][i]=fa[fa[u][i-1]][i-1];
}
for(int i=head[u];i;i=edge[i].next){
int v=edge[i].to;
if(v==father)continue;
dfs(v,u);
}
}
int LCA(int x,int y){
if(dep[x]<dep[y])
swap(x,y);
while(dep[x]>dep[y]){
x=fa[x][lg[dep[x]-dep[y]]-1];
}
if(x==y)return x;
for(int k=lg[dep[x]]-1;k>=0;--k){
if(fa[x][k]!=fa[y][k])
x=fa[x][k],y=fa[y][k];
}
return fa[x][0];
}
signed main(){
ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
cin>>n>>m>>s;
for(int i=1;i<n;++i){
int x,y;cin>>x>>y;
add(x,y);add(y,x);
}
for(int i=1;i<maxn;++i){
lg[i]=lg[i-1]+(1<<lg[i-1]==i);
}
dfs(s,0);
for(int i=1;i<=m;++i){
int a,b;cin>>a>>b;
cout<<LCA(a,b)<<endl;
}
}
P4281[AHOI2008]紧急集合、聚会
思路
求三个点的(lca),(xy,xz,yz)。我们容易知道的是必有两个(lca)是相等的(画图易得),然后我们选择不相等的那个(lca)作为最终的终点可。(画图易得)
倍增求LCA
#include<bits/stdc++.h>
using namespace std;
//#define int long long
int n,m,s;
const int maxn=5e5+10;
int head[maxn],tot=0;
struct edge{
int to,next;
}edge[maxn<<1];
void add(int u,int v){
edge[++tot].to=v;
edge[tot].next=head[u];
head[u]=tot;
}
int dep[maxn],fa[maxn][22],lg[maxn];
void dfs(int u,int father){
dep[u]=dep[father]+1;
fa[u][0]=father;
for(int i=1;i<=lg[dep[u]];++i){
fa[u][i]=fa[fa[u][i-1]][i-1];
}
for(int i=head[u];i;i=edge[i].next){
int v=edge[i].to;
if(v==father)continue;
dfs(v,u);
}
}
int LCA(int x,int y){
if(dep[x]<dep[y])
swap(x,y);
while(dep[x]>dep[y]){
x=fa[x][lg[dep[x]-dep[y]]-1];
}
if(x==y)return x;
for(int k=lg[dep[x]]-1;k>=0;--k){
if(fa[x][k]!=fa[y][k])
x=fa[x][k],y=fa[y][k];
}
return fa[x][0];
}
signed main(){
// ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
//cin>>n>>m;
scanf("%d%d",&n,&m);
for(int i=1;i<n;++i){
int x,y;
scanf("%d%d",&x,&y);
add(x,y);add(y,x);
}
for(int i=1;i<maxn;++i){
lg[i]=lg[i-1]+(1<<lg[i-1]==i);
}
dfs(1,0);
for(int i=1;i<=m;++i){
int x,y,z;
// cin>>x>>y>>z;
scanf("%d%d%d",&x,&y,&z);
int xy=LCA(x,y),xz=LCA(x,z),yz=LCA(y,z);
int ans;
if(xy==xz){
ans=dep[x]+dep[y]+dep[z]-dep[yz]-dep[yz]-dep[xz]+dep[yz]-dep[xz];
printf("%d %d
",yz,ans);
// cout<<yz<<" "<<ans<<endl;
}else if(xy==yz){
ans=dep[x]+dep[y]+dep[z]-dep[xz]-dep[xz]-dep[xy]+dep[xz]-dep[yz];
printf("%d %d
",xz,ans);
}else{
ans=dep[x]+dep[y]+dep[z]-dep[xy]-dep[xy]-dep[xz]+dep[xy]-dep[xz];
printf("%d %d
",xy,ans);
}
}
}
树剖求LCA
#include <bits/stdc++.h>
#define INF 0x3f3f3f3f
#define DOF 0x7f7f7f7f
#define endl '
'
#define mem(a, b) memset(a, b, sizeof(a))
#define debug(case, x) cout << case << " : " << x << endl
#define open freopen("ii.txt", "r", stdin)
#define close freopen("oo.txt", "w", stdout)
#define IO
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0)
#define pb push_back
using namespace std;
//#define int long long
#define lson rt << 1
#define rson rt << 1 | 1
typedef long long ll;
typedef pair<int, int> pii;
typedef pair<long long, long long> PII;
const int maxn = 5e5 + 10;
int n, m, s;
int head[maxn], tot;
struct edge {
int to, next;
} edge[maxn<<1];
int w[maxn], wt[maxn];
//w输入时的权值,wt编号后的权值
int son[maxn], id[maxn], fa[maxn], dep[maxn], sz[maxn], top[maxn], cnt = 0;
//son重儿子、id新编号、fa父亲节点、dep深度、sz子树大小、top顶端、cnt标号。
void add(int u, int v) {
edge[++tot].to = v;
edge[tot].next = head[u];
head[u] = tot;
}
void dfs1(int u, int father) {
dep[u] = dep[father] + 1;
sz[u] = 1;
fa[u] = father;
int maxson = -1;
for(int i = head[u]; i; i = edge[i].next) {
int v = edge[i].to;
if(v == father)continue;
dfs1(v, u);
sz[u] += sz[v];
if(sz[v] > maxson)
son[u] = v, maxson = sz[v];
}
}
void dfs2(int u, int topf) {
id[u] = ++cnt;
wt[cnt] = w[u];
top[u] = topf;
if(!son[u]) return ;
dfs2(son[u], topf);
for(int i = head[u]; i; i = edge[i].next) {
int v = edge[i].to;
if(v == fa[u] || v == son[u]) continue;
dfs2(v, v);
}
}
int LCA(int x,int y){
while(top[x]!=top[y]){
if(dep[top[x]]<dep[top[y]])swap(x,y);
x=fa[top[x]];
}
return dep[x]<dep[y]?x:y;
}
signed main() {
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
cin >> n >> m >> s;
for(int i = 1; i < n; ++i) {
int x, y;
cin >> x >> y;
add(x, y);
add(y, x);
}
dfs1(s,0);
dfs2(s, s);
for(int i = 1; i <= m; ++i) {
int a, b;
cin >> a >> b;
cout << LCA(a, b) << endl;
}
}