您的位置:首页 > 其它

P3379 【模板】最近公共祖先(LCA)

2017-07-14 10:03 471 查看
先跑出欧拉序列,并求出每个点在欧拉序列中最先出现的位置pos。
然后两点的lca就是对应的pos之间的最小值。rmq就好了。
#include<cstdio>
#include<cstring>
#include<iostream>
#include<vector>
#include<algorithm>
#include<set>
#include<map>
using namespace std;
#define rep(i,j,k) for(i=j;i<=k;++i)
#define per(i,j,k) for(i=j;i>=k;--i)
#define G getchar()
#define LL long long
#define pll pair<int,int>
#define mkp make_pair
#define X first
#define Y second
const int N=500005;
int n,m,rt;
int tot,he
,ne[N<<1],to[N<<1];
int phi[N<<1],pos
,ln,dep
;
int Min[N<<1][21],cs,bit[N<<1];
void read(int &x){
char ch=G;
while(ch<48||ch>57)ch=G;
for(x=0;ch>47&&ch<58;ch=G)x=x*10+ch-48;
}
void add(int x,int y){
to[++tot]=y;ne[tot]=he[x];he[x]=tot;
}
void DFS(int x){
int i,y;phi[pos[x]=++ln]=x;
for(i=he[x];i;i=ne[i])if(!pos[y=to[i]]){
dep[y]=dep[x]+1;DFS(y);phi[++ln]=x;
}
}
int get(int i,int j){
if(i>j)swap(i,j);
int t=bit[j-i+1];
int u=Min[i][t],v=Min[j-(1<<t)+1][t];
return dep[u]<dep[v]?u:v;
}
int main(){
int i,x,y,t;
for(x=2,t=1;x<1000000;x<<=1)bit[x]=t++;
rep(x,3,1000000)if(!bit[x])bit[x]=bit[x-1];
read(n);read(m);read(rt);tot=1;
rep(i,2,n){
read(x);read(y);
add(x,y);add(y,x);
}
dep[rt]=1;DFS(rt);
per(i,ln,1){
Min[i][0]=phi[i];
for(t=1;ln-i+1>=(1<<t);cs=max(cs,t++)){
x=i+(1<<t-1);
Min[i][t]=dep[Min[i][t-1]]<dep[Min[x][t-1]]?Min[i][t-1]:Min[x][t-1];
}

}
while(m--){
read(x);read(y);
printf("%d\n",get(pos[x],pos[y]));
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: