我不是很能理解出题人卡倍增的行为
查看原帖
我不是很能理解出题人卡倍增的行为
453460
End1essSummer楼主2021/11/28 17:48

RT,原倍增板子AC在重测后WA了11,12

同机房大佬的树刨也被卡了

接下来放出我的原AC代码

#include<bits/stdc++.h>
using namespace std;
//倍增法求lca
//算法原理 二进制
int fa[500010][21]/*记录父亲数组,fa[i][j]代表第i个点的第2^j个祖先*/,deep[500010]/*记录深度数组*/,n,m,s,lg[500010];
vector<int>Edge[500010];//存边
void dfs(int now/*现在哪个点了*/,int last/*上一个父亲结点*/){
    fa[now][0]=last;//now的第一个祖先就是last
    deep[now]=deep[fa[now][0]]+1;//它的深度就是它的父亲加一
    for(int i=1;i<20;i++){//遍历它父亲的所有父亲求出第now个点的第2^j个祖先
        fa[now][i]=fa[fa[now][i-1]][i-1];
    }int length=Edge[now].size();
    //cout<<now<<" "<<last<<" "<<deep[now]<<"\n";
    for(int i=0;i<length;i++){//遍历儿子
        if(Edge[now][i]==last) continue;
        dfs(Edge[now][i],now);
    }
}int lca(int u,int v){
    if(deep[u]<deep[v]){
        swap(u,v);//令u比v深,后面好计算  
    }int tmp=deep[v]-deep[u];
    while(deep[u]>deep[v]){
        u=fa[u][lg[deep[u]-deep[v]]-1];
    }if(u==v) return u;
    for(int j=lg[deep[u]]-1;j>=0;j--){//一起往上跳
        //cout<<u<<" "<<v<<"\n";
        if(fa[u][j]!=fa[v][j]){
            u=fa[u][j];
            v=fa[v][j];
        }
    }return fa[u][0];
}int main(){
    cin>>n>>m>>s;
    for(int i=1;i<=n;i++){
        lg[i]=lg[i-1];
        if(1<<lg[i-1]==i) lg[i]++;
    }
    for(int i=1;i<=n-1;i++){
        int x,y;
        cin>>x>>y;
        Edge[x].push_back(y);
        Edge[y].push_back(x);//添边,为dfs作准备
    }dfs(s,s);//我们以s为根节点,自然,s的深度为一并且它没有父亲(什,并dfs,为lca作准备
    for(int i=1;i<=m;i++){
        int u,v;
        cin>>u>>v;
        int ans=lca(u,v);//lca
        cout<<ans<<"\n";
    }return 0;
}
2021/11/28 17:48
加载中...