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(离线)算法:

原创模板:
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;
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,294评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,493评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,790评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,595评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,718评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,906评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,053评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,797评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,250评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,570评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,711评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,388评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,018评论 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,796评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,023评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,461评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,595评论 2 350

推荐阅读更多精彩内容