最近公共祖先LCA

code:

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#define maxn 500010
using namespace std;
template<typename T>
inline void read(T &x){
    x=0;bool flag=0;char c=getchar();
    for(;!isdigit(c);c=getchar()) if(c=='-') flag=1;
    for(;isdigit(c);c=getchar()) x=x*10+(c^48);
    if(flag) x=-x;
}

int n,m,s,x,y,a,b;
int k=0,lg[maxn],f[maxn][25],head[maxn],deep[maxn];
struct node{
    int v;
    int to;
}e[2*maxn];

void add(int u,int v){
    k++;
    e[k].to=v;
    e[k].v=head[u];
    head[u]=k;
}

void dfs(int u,int fa){
    deep[u]=deep[fa]+1;
    f[u][0]=fa;
    for(int i=1;(1<<i)<=deep[u];i++) f[u][i]=f[f[u][i-1]][i-1];
    for(int i=head[u];i!=-1;i=e[i].v){
        int to=e[i].to;
        if(to!=fa) dfs(to,u); 
    }
}

int lca(int x,int y){
    if(deep[x]<deep[y]) swap(x,y);
    while(deep[x]>deep[y]) x=f[x][lg[deep[x]-deep[y]]-1];
    if(x==y) return x;
    for(int i=lg[deep[x]]-1;i>=0;i--){
        if(f[x][i]!=f[y][i]){
            x=f[x][i];
            y=f[y][i];
        }
    }
    return f[x][0];
}

int main(){
    read(n),read(m),read(s);
    memset(head,-1,sizeof(head));
    for(int i=1;i<=n-1;i++){
        read(x),read(y);
        add(x,y);
        add(y,x);
    }
    for(int i=1;i<=n;i++) lg[i]=lg[i-1]+(1<<lg[i-1]==i);
    dfs(s,0);
    for(int i=1;i<=m;i++){
        read(a),read(b);
        cout<<lca(a,b)<<endl;
    }
    return 0;
}

某膜你赛题:

code:

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#define maxn 200010
using namespace std;
template<typename T>
inline void read(T &x){
    x=0; bool flag=0; char c=getchar();
    for(;!isdigit(c);c=getchar()) if(c=='-') flag=1;
    for(;isdigit(c);c=getchar()) x=x*10+(c^48);
    if(flag) x=-x;
}

int n,t,x,y,a,b,c,d;
int root,k=0,fa[maxn],head[maxn],deep[maxn],p[maxn][21];

struct node{
    int v,next;
}e[maxn*2];

void add(int u,int v){
    e[k].v=v;
    e[k].next=head[u];
    head[u]=k++;
}
void dfs(int u,int fa){
    deep[u]=deep[fa]+1;
    p[u][0]=fa;
    for(int i=1;(1<<i)<=deep[u];i++) p[u][i]=p[p[u][i-1]][i-1];
    for(int i=head[u];i!=-1;i=e[i].next){
        int v=e[i].v;
        if(v!=fa) dfs(v,u);
    }
}

int lca(int a,int b){
    if(deep[a]>deep[b]) swap(a,b);
    for(int i=20;i>=0;i--)
        if(deep[a]<=deep[b]-(1<<i))
            b=p[b][i];
    if(a==b) return a;
    for(int i=20;i>=0;i--){
        if(p[a][i]!=p[b][i]) a=p[a][i],b=p[b][i];
    }
    return p[a][0];
}

int dis(int a,int b){//注意求的是这个点在不在树的这一段上,所以不能直接比较LCA啊QAQ 
    int c=lca(a,b);
    return abs(deep[c]-deep[a])+abs(deep[c]-deep[b]);
} 

int main(){
//    freopen("assassin.in","r",stdin);
//    freopen("assassin.out","w",stdout);
    read(n),read(t);
    memset(head,-1,sizeof(head));
    for(int i=1;i<=n-1;i++){
        read(x),read(y);
        fa[y]=x;
        add(x,y);
        add(y,x);
    }
    for(int i=1;i<=n;i++){
        if(fa[i]==0){
            root=i;
            break;
        }
    }
//    cout<<root<<endl;
    dfs(root,0);
    for(int i=1;i<=t;i++){
        read(a),read(b),read(c),read(d);
//        read(a),read(b);
        int ans1=lca(a,b);
        int ans2=lca(c,d);
//        cout<<"***"<<ans1<<" "<<ans2<<"***"<<endl;
        if(dis(a,ans2)+dis(b,ans2)==dis(a,b)||dis(c,ans1)+dis(d,ans1)==dis(c,d)) cout<<"YES"<<endl;//******** 
        else cout<<"NO"<<endl;
    }
    return 0;
}
/*
5 5 
2 5 
4 2 
1 3 
1 4 
5 1 5 1 
2 2 1 4 
4 1 3 4 
3 1 1 5 
3 5 1 4 
*/
/*
YES 
NO 
YES 
YES 
YES 
*/

 

posted @ 2021-02-22 19:52  DReamLion  阅读(32)  评论(0编辑  收藏  举报