Least Common Ancestor

struct LeastCommonAncestor
{
    static const int __=10005;
    static const int logn=15;
    struct edge
    {
        int x,val;
        edge(int x,int y):
            x(x),val(y) {}
    };

    vector<edge>G[__];
    int n,pre[__][logn],dis[__][logn],dep[__];

    void add_edge(int x,int y,int z)
    {
        G[x].pb(edge(y,z));
    }

    void dfs(int x,int fa,int dist)
    {
        pre[x][0]=fa,dis[x][0]=dist,dep[x]=dep[fa]+1;
        fup(i,0,sz(G[x])-1)
            if(G[x][i].x!=fa)
                dfs(G[x][i].x,x,G[x][i].val);
    }

    void init(int _n)
    {
        n=_n;
        dfs(1,0,0);
        fup(i,1,logn-1)
            fup(j,1,n)
            {
                pre[j][i]=pre[pre[j][i-1]][i-1];
                dis[j][i]=dis[j][i-1]+dis[pre[j][i-1]][i-1];
            }
    }

    int get_lca(int x,int y)
    {
        if(dep[x]<dep[y])swap(x,y);
        fdn(i,logn-1,0)
            if(pre[x][i] && dep[pre[x][i]]>=dep[y])
                x=pre[x][i];
        if(x==y)return x;
        fdn(i,logn-1,0)
            if(pre[x][i]!=pre[y][i])
                x=pre[x][i],y=pre[y][i];
        return pre[x][0];
    }

    int get_dis(int x,int y)
    {
        if(dep[x]<dep[y])swap(x,y);
        int sum=0;
        fdn(i,logn-1,0)
            if(pre[x][i] && dep[pre[x][i]]>=dep[y])
                sum+=dis[x][i],x=pre[x][i];
        if(x==y)return sum;
        fdn(i,logn-1,0)
            if(pre[x][i]!=pre[y][i])
                sum+=dis[x][i]+dis[y][i],x=pre[x][i],y=pre[y][i];
        sum+=dis[x][0]+dis[y][0];
        return sum;
    }

    int get_kth(int x,int y,int k)
    {
        int lca=get_lca(x,y);
        if(k==dep[x]-dep[lca]+1)return lca;
        if(k<dep[x]-dep[lca]+1)
        {
            k--;
            fdn(i,logn-1,0)
                if(pre[x][i] && k>=(1<<i))
                    k-=(1<<i),x=pre[x][i];
            return x;
        }
        if(k>dep[x]-dep[lca]+1)
        {
            k=dep[x]+dep[y]-2*dep[lca]-k+1;
            fdn(i,logn-1,0)
                if(pre[y][i] && k>=(1<<i))
                    k-=(1<<i),y=pre[y][i];
            return y;
        }
    }

    void clear(){fup(i,1,n)G[i].clear();}
}lca;

題目鏈接:最近公共祖先

樹鏈剖分:

struct bian
{
    int nex,nex_node;
    bian(int nex=0,int nex_node=0):
        nex(nex),nex_node(nex_node) {}
} edge[1000005];

int head[500005],edge_num=0;

void add_edge(int now,int nex)
{
    edge[edge_num]=bian(nex,head[now]);
    head[now]=edge_num++;
}

int pre[500005],dep[500005];
int top[500005],heavy[500005];

int dfs(int x,int fa,int depth)
{
    dep[x]=depth,pre[x]=fa;
    int res=1,maxx=0;
    for(int i=head[x]; ~i; i=edge[i].nex_node)
    {
        int nex=edge[i].nex;
        if(nex==fa)continue;
        int t=dfs(nex,x,depth+1);
        if(t>maxx)maxx=t,heavy[x]=nex;
        res+=t;
    }
    return res;
}

void slpf(int x,int fa,int tp)
{
    top[x]=tp;
    if(heavy[x])slpf(heavy[x],x,tp);
    for(int i=head[x]; ~i; i=edge[i].nex_node)
    {
        int nex=edge[i].nex;
        if(nex==fa)continue;
        if(nex!=heavy[x])slpf(nex,x,nex);
    }
}

int lca(int x,int y)
{
    while(top[x]!=top[y])
        if(dep[top[x]]>dep[top[y]])
            x=pre[top[x]];
        else y=pre[top[y]];
    if(dep[x]>dep[y])swap(x,y);
    return x;
}

int main()
{
    memset(head,-1,sizeof(head));
    int n,q,root,x,y;
    scanf("%d%d%d",&n,&q,&root);
    for(int i=1; i<=n-1; i++)
    {
        scanf("%d%d",&x,&y);
        add_edge(x,y);
        add_edge(y,x);
    }
    dfs(root,0,1);
    slpf(root,0,root);
    while(q--)
    {
        scanf("%d%d",&x,&y);
        printf("%d\n",lca(x,y));
    }
    return 0;
}

Tarjan(離線)算法:

原創(chuàng)模板:
int n;
vector<int>G[10005];
int pre[10005];
int vis[10005];
int alr[10005];

void init(int x)
{
    for(int i=1; i<=x; i++)
        pre[i]=i;
}

int a,b;

int find(int x)
{
    if(pre[x]==x)return x;
    else return find(pre[x]);
}

int flag=0;

void dfs(int x,int fa)
{
    if(flag)return;
    int len=G[x].size();
    for(int i=0; i<len; i++)
    {
        int next=G[x][i];
        if(!alr[next])
        {
            alr[next]=1;
            dfs(next,x);
            if(flag)return;
            alr[next]=0;
        }
    }
    vis[x]=1;
    if(x==a&&vis[b])flag=find(b);
    if(x==b&&vis[a])flag=find(a);
    pre[x]=fa;
}

int main()
{
    int T,mk;
    scanf("%d",&T);
    while(T--)
    {
        flag=0;
        memset(vis,0,sizeof(vis));
        memset(alr,0,sizeof(alr));
        scanf("%d",&n);
        init(n);
        for(int i=0; i<n-1; i++)
        {
            int x,y;
            scanf("%d%d",&x,&y);
            if(i==0)mk=x;
            G[x].push_back(y);
            G[y].push_back(x);
        }
        scanf("%d%d",&a,&b);
        alr[mk]=1;
        dfs(mk,mk);
        printf("%d\n",flag);
        for(int i=1; i<=n; i++)G[i].clear();
    }
    return 0;
}

RMQ-ST(在線)算法:

struct node
{
    int val,id;
};

vector<int>G[500005];
int vis[500005];
int first[500005];
node minn[500005][21];
int cont=1;

void dfs(int node,int depth)
{
    minn[cont][0].id=node;
    if(!first[node])first[node]=cont;
    minn[cont++][0].val=depth;
    int len=G[node].size();
    for(int i=0; i<len; i++)
        if(!vis[G[node][i]])
        {
            vis[G[node][i]]=1;
            dfs(G[node][i],depth+1);
            vis[G[node][i]]=0;
            minn[cont][0].id=node;
            minn[cont++][0].val=depth;
        }
}

void rmq(int n)
{
    for(int j=1; (1<<j)<=n; j++)
        for(int i=1; i+(1<<(j-1))<=n; i++)
            if(minn[i][j-1].val<minn[i+(1<<(j-1))][j-1].val)
            {
                minn[i][j].val=minn[i][j-1].val;
                minn[i][j].id=minn[i][j-1].id;
            }
            else
            {
                minn[i][j].val=minn[i+(1<<(j-1))][j-1].val;
                minn[i][j].id=minn[i+(1<<(j-1))][j-1].id;
            }
}

int findmin(int l,int r)
{
    int k=0;
    if(l>r)swap(l,r);
    while((1<<(k+1))<=r-l+1)k++;
    if(minn[l][k].val<minn[r-(1<<k)+1][k].val)
        return minn[l][k].id;
    else
        return minn[r-(1<<k)+1][k].id;
}

int main()
{

    int n,m,x,y,a,b,root;
    scanf("%d%d%d",&n,&m,&root);
    for(int i=0; i<n-1; i++)
    {
        scanf("%d%d",&x,&y);
        G[x].push_back(y);
        G[y].push_back(x);
    }
    vis[root]=1;
    dfs(root,1);
    rmq(cont);
    for(int i=0; i<m; i++)
    {
        scanf("%d%d",&a,&b);
        printf("%d\n",findmin(first[a],first[b]));
    }
    return 0;
}

題目鏈接:最近公共祖先

在線:
struct node
{
    int val,id;
};
map<string,int>mp1;
map<int,string>mp2;
vector<int>G[200005];
int deep[200005],order[200005],first[200005],pre[200005],cont;
bool vis[200005];
node minn[200005][20];
void dfs(int node,int depth)
{
    vis[node]=true;
    order[cont]=node;
    if(!first[node])first[node]=cont;
    deep[cont++]=depth;
    int len=G[node].size();
    for(int i=0; i<len; i++)
    {
        int next=G[node][i];
        dfs(next,depth+1);
        order[cont]=node;
        deep[cont++]=depth;
    }
}
void rmq(int n)
{
    for(int j=1; (1<<j)<=n; j++)
        for(int i=1; i+(1<<(j-1))<=n; i++)
            if(minn[i][j-1].val<minn[i+(1<<(j-1))][j-1].val)
            {
                minn[i][j].val=minn[i][j-1].val;
                minn[i][j].id=minn[i][j-1].id;
            }
            else
            {
                minn[i][j].val=minn[i+(1<<(j-1))][j-1].val;
                minn[i][j].id=minn[i+(1<<(j-1))][j-1].id;
            }
}
int findmin(int l,int r)
{
    int k=0;
    if(l>r)swap(l,r);
    while((1<<(k+1))<=r-l+1)k++;
    if(minn[l][k].val<minn[r-(1<<k)+1][k].val)
        return minn[l][k].id;
    else return minn[r-(1<<k)+1][k].id;
}
int find(int x)
{
    if(pre[x]==x)return x;
    else return find(pre[x]);
}

int main()
{
    int n,k=1;
    char a[50],b[50];
    scanf("%d",&n);
    for(int i=1;i<=100;i++)
        pre[i]=i;
    for(int i=0; i<n; i++)
    {
        scanf("%s%s",a,b);
        if(!mp1[a])
        {
            mp1[a]=k;
            mp2[k++]=a;
        }
        if(!mp1[b])
        {
            mp1[b]=k;
            mp2[k++]=b;
        }
        G[mp1[a]].push_back(mp1[b]);
    }
    cont=1;
    for(int i=1; i<k; i++)
        if(!vis[find(i)])dfs(find(i),1);
    for(int i=1; i<cont; i++)
    {
        minn[i][0].val=deep[i];
        minn[i][0].id=order[i];
    }
    rmq(cont);
    char x[50],y[50];
    int T;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%s%s",x,y);
        cout<<mp2[findmin(first[mp1[x]],first[mp1[y]])]<<'\n';
    }
    return 0;
}

題目鏈接:最近公共祖先

離線:
struct node
{
    int nex,id;
} t;

int pre[100005];
int ans[100005];
bool vis[100005];
bool alr[100005];
char re[100005][50];
map<string,int>mp;
vector<int>G[100005];
vector<node>Que[100005];

int find(int x)
{
    if(pre[x]==x)return x;
    else 
    return pre[x]=find(pre[x]);
}

void dfs(int fa,int x)
{
    int len=G[x].size();
    for(int i=0; i<len; i++)
    {
        int nex=G[x][i];
        if(!alr[nex])
        {
            alr[nex]=true;
            dfs(x,nex);
            alr[nex]=false;
        }
    }
    vis[x]=true;
    len=Que[x].size();
    for(int i=0; i<len; i++)
    {
        int nex=Que[x][i].nex;
        int id=Que[x][i].id;
        if(vis[nex]&&!ans[id])ans[id]=find(nex);
    }
    pre[x]=find(fa);
}

void init(int n)
{
    for(int i=1; i<=n; i++)
        pre[i]=i;
}

int main()
{
    int n,q,cont=1;
    char fa[50],son[50],name1[50],name2[50];
    scanf("%d",&n);
    init(n);
    cont=1;
    for(int i=0; i<n; i++)
    {
        scanf("%s%s",fa,son);
        int idfa=mp[fa],idson=mp[son];
        if(!idfa)
        {
            memcpy(re[cont],fa,sizeof(re[cont]));
            idfa=mp[fa]=cont++;
        }
        if(!idson)
        {
            memcpy(re[cont],son,sizeof(re[cont]));
            idson=mp[son]=cont++;
        }
        G[idfa].push_back(idson);
    }
    scanf("%d",&q);
    for(int i=1; i<=q; i++)
    {
        scanf("%s%s",name1,name2);
        int id1=mp[name1],id2=mp[name2];
        t.id=i;
        t.nex=id2;
        Que[id1].push_back(t);
        t.nex=id1;
        Que[id2].push_back(t);
    }
    for(int i=1; i<cont; i++)
        if(!vis[find(i)])
        {
            alr[find(i)]=true;
            dfs(find(i),find(i));
        }
    for(int i=1; i<=q; i++)
        printf("%s\n",re[ans[i]]);
}

題目鏈接:最近公共祖先

LCT:

#define ls(x) tree[x].lson
#define rs(x) tree[x].rson
#define fa(x) tree[x].pre
#define grafa(x) tree[tree[x].pre].pre

struct bian
{
    int nex,nex_node;
    bian(int x=0,int y=0):
        nex(x),nex_node(y) {}
} edge[1000005];

int head[500005],edge_num=0;

void add_edge(int now,int nex)
{
    edge[edge_num]=bian(nex,head[now]);
    head[now]=edge_num++;
}

int path_pre[500005];

void dfs(int x,int fa)
{
    path_pre[x]=fa;
    for(int i=head[x]; ~i; i=edge[i].nex_node)
    {
        int nex=edge[i].nex;
        if(nex==fa)continue;
        dfs(nex,x);
    }
}

struct node
{
    int pre,lson,rson;
    int val,siz;
    node(int pre=-1,int lson=-1,int rson=-1,
         int val=0,int siz=0):
        pre(pre),lson(lson),rson(rson),
        val(val),siz(siz) {}
} tree[500005];


int root=-1;

void pushup(int x)
{
    tree[x].siz=1;
    if(~ls(x))
        tree[x].siz+=tree[ls(x)].siz;
    if(~rs(x))
        tree[x].siz+=tree[rs(x)].siz;
}

void zig(int x)
{
    int y=fa(x);
    if(~fa(y))
        if(ls(fa(y))==y)
            ls(fa(y))=x;
        else rs(fa(y))=x;
    fa(x)=fa(y),fa(y)=x;
    ls(y)=rs(x);
    if(~ls(y))fa(ls(y))=y;
    rs(x)=y;
    if(fa(x)==-1)root=x;
    pushup(y),pushup(x);
}

void zag(int x)
{
    int y=fa(x);
    if(~fa(y))
        if(ls(fa(y))==y)
            ls(fa(y))=x;
        else rs(fa(y))=x;
    fa(x)=fa(y),fa(y)=x;
    rs(y)=ls(x);
    if(~rs(y))fa(rs(y))=y;
    ls(x)=y;
    if(fa(x)==-1)root=x;
    pushup(y),pushup(x);
}

void splay(int x,int wz=-1)
{
    while(x!=wz && fa(x)!=wz)
        if(grafa(x)==wz)
            if(ls(fa(x))==x)zig(x);
            else zag(x);
        else if(ls(fa(x))==x && ls(grafa(x))==fa(x))
            zig(fa(x)),zig(x);
        else if(rs(fa(x))==x && rs(grafa(x))==fa(x))
            zag(fa(x)),zag(x);
        else if(ls(fa(x))==x && rs(grafa(x))==fa(x))
            zig(x),zag(x);
        else if(rs(fa(x))==x && ls(grafa(x))==fa(x))
            zag(x),zig(x);
}

int aux_root(int x)
{
    while(~ls(x))x=ls(x);
    return x;
}

int access(int x)
{
    int deper=-1;
    while(~x)
    {
        splay(x);
        fa(rs(x))=-1;
        rs(x)=deper;
        pushup(x);
        if(~deper)fa(deper)=x;
        deper=x;
        x=path_pre[aux_root(x)];
    }
    return deper;
}

int lca(int x,int y)
{
    access(x);
    return access(y);
}

void show(int n)
{
    for(int i=1;i<=n;i++)
        printf("%d: ls:%d rs:%d fa:%d\n",i,ls(i),rs(i),fa(i));
}

int main()
{
    memset(head,-1,sizeof(head));
    int n,q,root;
    scanf("%d%d%d",&n,&q,&root);
    for(int i=1; i<n; i++)
    {
        int x,y;
        scanf("%d%d",&x,&y);
        add_edge(x,y);
        add_edge(y,x);
    }
    dfs(root,-1);
    while(q--)
    {
        int x,y;
        scanf("%d%d",&x,&y);
        printf("%d\n",lca(x,y));
    }
    return 0;
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末确虱,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子锌妻,更是在濱河造成了極大的恐慌,老刑警劉巖葡秒,帶你破解...
    沈念sama閱讀 218,941評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件彤钟,死亡現(xiàn)場離奇詭異,居然都是意外死亡卸例,警方通過查閱死者的電腦和手機(jī)姥闪,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,397評論 3 395
  • 文/潘曉璐 我一進(jìn)店門始苇,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人筐喳,你說我怎么就攤上這事催式。” “怎么了避归?”我有些...
    開封第一講書人閱讀 165,345評論 0 356
  • 文/不壞的土叔 我叫張陵荣月,是天一觀的道長。 經(jīng)常有香客問我梳毙,道長哺窄,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,851評論 1 295
  • 正文 為了忘掉前任账锹,我火速辦了婚禮萌业,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘奸柬。我一直安慰自己咽白,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,868評論 6 392
  • 文/花漫 我一把揭開白布鸟缕。 她就那樣靜靜地躺著县爬,像睡著了一般溉卓。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上没陡,一...
    開封第一講書人閱讀 51,688評論 1 305
  • 那天蹲蒲,我揣著相機(jī)與錄音番甩,去河邊找鬼。 笑死届搁,一個(gè)胖子當(dāng)著我的面吹牛缘薛,可吹牛的內(nèi)容都是我干的窍育。 我是一名探鬼主播,決...
    沈念sama閱讀 40,414評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼宴胧,長吁一口氣:“原來是場噩夢啊……” “哼漱抓!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起恕齐,我...
    開封第一講書人閱讀 39,319評論 0 276
  • 序言:老撾萬榮一對情侶失蹤乞娄,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后显歧,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體仪或,經(jīng)...
    沈念sama閱讀 45,775評論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,945評論 3 336
  • 正文 我和宋清朗相戀三年士骤,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了范删。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,096評論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡拷肌,死狀恐怖到旦,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情廓块,我是刑警寧澤厢绝,帶...
    沈念sama閱讀 35,789評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站带猴,受9級特大地震影響昔汉,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜拴清,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,437評論 3 331
  • 文/蒙蒙 一靶病、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧口予,春花似錦娄周、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,993評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至木张,卻和暖如春众辨,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背舷礼。 一陣腳步聲響...
    開封第一講書人閱讀 33,107評論 1 271
  • 我被黑心中介騙來泰國打工鹃彻, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人妻献。 一個(gè)月前我還...
    沈念sama閱讀 48,308評論 3 372
  • 正文 我出身青樓蛛株,卻偏偏與公主長得像团赁,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子谨履,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,037評論 2 355

推薦閱讀更多精彩內(nèi)容

  • LCA 最近公共祖先在一棵沒有環(huán)的樹上欢摄,每個(gè)節(jié)點(diǎn)肯定有其父親節(jié)點(diǎn)和祖先節(jié)點(diǎn),而最近公共祖先屉符,就是兩個(gè)節(jié)點(diǎn)在這棵樹上...
    Gitfan閱讀 936評論 0 0
  • 在一棵沒有環(huán)的樹上剧浸,每個(gè)節(jié)點(diǎn)肯定有其父親節(jié)點(diǎn)和祖先節(jié)點(diǎn),而最近公共祖先矗钟,就是兩個(gè)節(jié)點(diǎn)在這棵樹上深度最大的公共的祖先...
    Joseph_Z閱讀 2,056評論 0 0
  • 一. 尋找父親節(jié)點(diǎn)和孩子節(jié)點(diǎn) 首先需要回顧一下希爾伯特曲線的生成方式唆香,具體代碼見筆者上篇文章的分析,在這個(gè)分析中吨艇,...
    一縷殤流化隱半邊冰霜閱讀 2,433評論 6 15
  • 在一棵樹上查詢?nèi)我鈨蓚€(gè)點(diǎn)的最近公共祖先躬它,或求最短距離的離線算法tarjan,基于dfs遍歷和并查集东涡,在查詢時(shí)倍增直...
    simon_orange閱讀 1,277評論 0 0
  • 他們說冯吓,所有微小而確實(shí)存在的幸福被統(tǒng)稱為小確幸。 對我來說小確幸就是在夜雨后的清晨疮跑,踩著幾斤重的鞋泥跟在前方拿著砍...
    小小七的一切閱讀 157評論 0 0