1. 程式人生 > >C++ P3379 【模板】最近公共祖先(LCA)

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

早就想寫LCA了,奈何沒有dfs基礎,先做了最小生成樹

廢話就說到這裡,上程式碼。

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
const int maxn=500000+2;
int n,m,s;
int k=0;
int head[maxn],d[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){//預處理
    d[u]=d[fa]+1;
    p[u][0]=fa;
    for(int i=1;(1<<i)<=d[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(d[a]>d[b])swap(a,b);
    for(int i=20;i>=0;i--)
    if(d[a]<=d[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])continue;
    else a=p[a][i],b=p[b][i];
    return p[a][0];
}
int main(){
    memset(head,-1,sizeof(head));
    int a,b;
    scanf("%d%d%d",&n,&m,&s);
    for(int i=0;i<n-1;i++){
        scanf("%d%d",&a,&b);
        add(a,b);
        add(b,a);
    }
    dfs(s,0);
    for(int i=1;i<=m;i++){
        scanf("%d%d",&a,&b);
        int ans=lca(a,b);
        printf("%d\n",ans);
    }
    return 0;
}

為什麼沒有註釋呢?因為我把程式碼背過了。

所以還是分享一下我背程式碼的經驗吧。

  1. 背程式碼之前請找一個大佬講一下這個演算法,讓你大概瞭解演算法的執行過程(其實就是半懂不懂 )!!
  2. 一句一句的背,不要貪快
  3. 一個程式碼塊一個程式碼塊的背,比如賦值一部分 迴圈一部分,最終一個方法一個方法的背

另外,十分感謝gzh大佬為我們講解了LCA演算法QAQ