1. 程式人生 > >洛谷 3379 LCA模板

洛谷 3379 LCA模板

哈哈哈 ron pri 地方 來源 \n 找我 註意 main

本人最近剛接觸到LCA,先是在vjudge的團隊裏做到了一到倍增LCA找父親(codeforces 519E),然後求出有多少個點到訪問的x,y這兩個節點的距離相同。

洛谷題號:CF519E

鏈接:https://www.luogu.org/problemnew/show/CF519E

我有一個程序瘋狂無限制第7個點爆MLE到現在都不知道為什麽。

代碼請見:https://www.luogu.org/discuss/show?postid=48843

希望有大佬能夠指點迷津。 可以在洛谷評論也可以在這裏評論,或者私信我的qq也行

QQ:2320993191

但是雖然說是一直MLE過不去這道題目,但是對LCA我初步有了一定的理解,然後我就按耐不住激動地心情,來到洛谷做了一下模板LCA。

這裏我要講兩個註意點:

1.在我們在做dfs預處理f數組的時候,i不能倒著掃,因為每一個f[x][i]都來源於比自己要小的f[f[x][i-1]][i-1],所以如果倒著掃就會出現問題。我剛開始也就是因為這個錯了。

2.當我們在把x節點和y節點跳到同一個深度以及之後達到同一深度再往上跳的時候,i都需要倒著掃,這裏我們需要想一下,我舉一個例子,如果我現在需要向上跳5個深度,那麽如果我i=1的時候跳(1<<1)也就是2個深度的時候,我還需要跳3個深度,但是當我下一次要跳的時候 i已經等於2了,又因為(1<<2)等於4了,已經超過了3個深度所以已經不能跳了。所以必須是要倒著掃的,其次我們在想一下,即使我們倒著掃,我們也無法判斷,這次往上跳完了之後到底是已經在我們所需要求的LCA只上,還是恰好是我們需要求的LCA,所以當f[x][i]==f[y][i]的時候我們幹脆不跳,這樣等我們操作完了之後,只需要在往上跳一個深度,那麽那個節點就一定是我們所想要的LCA. 下面是我的AC代碼,大家可以參考一下。如果有什麽地方有問題歡迎大家提出,也隨時歡迎大家來找我一起討論OI問題,其他問題也可以啦哈哈哈哈哈哈哈,比如說抑郁不得誌(這麽大佬的你們肯定不會抑郁不得誌的),我可以幫你解脫煩惱O(∩_∩)O哈哈~

#include<cstdio>
#include<algorithm>
using namespace std;
const int N=1000010;
int n,m,s,x,y,ans,top;
int first[N],next[N],get[N],deep[N];
int f[N][32];
void add(int x,int y){
    get[++top]=y;
    next[top]=first[x];
    first[x]=top;
}
void dfs(int x,int fa,int deep_){
    deep[x]=deep_;
    f[x][0]=fa;
    for (int i=1;(1<<i)<=deep_;++i)
    f[x][i]=f[f[x][i-1]][i-1];
    for (int i=first[x];i;i=next[i]){
        int v=get[i];
        if (v==fa) continue;
        dfs(v,x,deep_+1);
    }
}
void LCA(int a,int b){
    if (deep[a]>deep[b]) swap(a,b); //a淺 b深
    for (int i=31;i>=0;--i){
        if (deep[b]-(1<<i)<deep[a]) continue;
        b=f[b][i];
    }
    if (a==b) {
        ans=a;
        return;
    }
    for (int i=31;i>=0;--i){
        if(f[a][i]==f[b][i]) continue;
        a=f[a][i];
        b=f[b][i];
    }
    ans=f[a][0];
}
int main(){
    //freopen(".in","r",stdin);
    scanf("%d%d%d",&n,&m,&s);
    for (int i=1;i<=n-1;++i){
        scanf("%d%d",&x,&y);
        add(x,y);
        add(y,x);
    }
    dfs(s,0,1);
    for (int i=1;i<=m;++i){
        scanf("%d%d",&x,&y);
        LCA(x,y);
        printf("%d\n",ans);
    }
}

洛谷 3379 LCA模板