zoukankan      html  css  js  c++  java
  • Tarjan之求LCA

    Tarjan之求LCA

    不要问我为什么写完Tarjan还要再补一句“求LCA的那个”

    因为只说Tarjan的话完全不知道你指的是哪个算法……

    劳模Tarjan同志证明了好多算法,而且全都叫Tarjan算法(是不会起名了吗x)

    这个Tarjan是一个求LCA的离线算法

    关于什么是在线什么是离线……

    所谓的在线算法就是实时性的,比方说,给你一个输入,算法就给出一个输出,就像是http请求,请求网页

    一样。给一个实时的请求,就返回给你一个请求的网页。而离线算法则是要求一次性读入所有的请求,然后在

    统一处理。而在处理的过程中不一定是按照请求的输入顺序来处理的。说不定后输入的请求在算法的执行过程

    中是被先处理的。”

    ↑从网上抄来的w↑感觉很好懂……

    因为是离线做法,重新排列了一下解决询问的顺序,所以要比在线算法快

    Tarjan的前置技能是dfs和并查集,不会的赶紧去学x

    那么正片开始!

    因为这是个离线算法,所以读进来各条边之后继续读进来所有询问并存起来

    然后从根开始dfs

    访问到每个点的时候,先遍历从这个点u出去的所有边,dfs未访问过的点v,访问后把这个点并到u的并查集上

    然后扫一遍和u有关的所有询问及其涉及到的点v

    如果点v已经被访问过了,那么说明u和v的LCA已经算好了

    真相只有一个,LCA就是点v所在的并查集的祖先

    赶紧存进答案数组里……

    全部dfs完成后,答案也全部算完了,按询问序输出答案就OK了

    具体实现可以看代码OvO

    //Tarjan lca 
    #include<iostream>
    #include<cstdio>
    using namespace std;
    const int N=500009;
    int n,m,s,cnt,tot,ep[N],qp[N],fa[N];
    bool vis[N];
    struct edge{
           int to,nex;
    }e[N<<1];
    struct query{
           int to,nex,ans;
    }q[N<<1];
    int read()
    {
        int an=0;
        char ch=getchar();
        while(!('0'<=ch&&ch<='9'))ch=getchar();
        while('0'<=ch&&ch<='9'){an=an*10+ch-'0';ch=getchar();}
        return an;
    }
    int found(int x)
    {
        if(x==fa[x])return x;
        return fa[x]=found(fa[x]);
    }
    void adde(int u,int v)
    {
         ++cnt;
         e[cnt].to=v;
         e[cnt].nex=ep[u];
         ep[u]=cnt;
    }
    void addq(int u,int v)
    {
         ++tot;
         q[tot].to=v;
         q[tot].nex=qp[u];
         qp[u]=tot;
    }
    void dfs(int u)
    {
         vis[u]=1;fa[u]=u;
         for(int i=ep[u];i;i=e[i].nex)
         {
           int v=e[i].to;
           if(!vis[v]){dfs(v);fa[v]=u;}
         }
         for(int i=qp[u];i;i=q[i].nex)
         {
           int v=q[i].to;
           if(vis[v])
           {
             q[i].ans=found(v);
             if(i&1)q[i+1].ans=q[i].ans;
             else   q[i-1].ans=q[i].ans;
           }
         }
    }
    int main()
    {
        n=read(),m=read(),s=read();
        for(int i=1;i<n;++i)
        {
          int x=read(),y=read();
          adde(x,y);adde(y,x);
        }
        for(int i=1;i<=m;++i)
        {
          int x=read(),y=read();
          addq(x,y);addq(y,x);
        }
        dfs(s);
        for(int i=1;i<=m;++i)
        printf("%d
    ",q[i<<1].ans);
        return 0;
    }
    Tarjan LCA(wypx)

    偷着放一份s菌的代码

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<queue>
    #include<algorithm>
    using namespace std;
    int read(){
        int an=0,f=1;char ch=getchar();
        while(!('0'<=ch&&ch<='9')){if(ch=='-')f=-f;ch=getchar();}
        while('0'<=ch&&ch<='9'){an=an*10+ch-'0';ch=getchar();}
        return an*f;
    }
    int n,m,s,cnt,qf[500099],f[500099],fa[500099],ans[500099<<1];
    int x,y;
    bool vis[500099];
    int found(int x){
        if(fa[x]!=x)fa[x]=found(fa[x]);
        return fa[x];}
    struct saber{
    int to,nex;
    }b[500099<<1];
    struct question{
    int to,nex;
    }qu[500099<<1];
    void add(int x,int y){
        cnt++;b[cnt].to=y;
        b[cnt].nex=f[x];f[x]=cnt;
    }
    void add(int x,int y,int z){
        qu[z].to=y;
        qu[z].nex=qf[x];
        qf[x]=z;
    }
    void dfs(int x){
        fa[x]=x;vis[x]=1;//cout<<x<<" ";
        for(int i=f[x];i;i=b[i].nex){
            int v=b[i].to;
            if(!vis[v]){
                dfs(v);
                fa[v]=x;
            }
        }
        for(int i=qf[x];i;i=qu[i].nex){
            int v=qu[i].to;
            if(vis[v]){
                ans[i]=found(v);
                if(i&1)ans[i+1]=ans[i];
                else ans[i-1]=ans[i];
            }
        }
    }
    int main(){
        n=read();m=read();s=read();
        for(int i=1;i<n;i++){
            int x,y;x=read();y=read();
            add(x,y);add(y,x);
        }
        for(int i=1;i<=m;i++){
            x=read();y=read();
            add(x,y,i*2-1);add(y,x,i*2);
        }
        dfs(s);
        for(int i=1;i<=m;i++){
            cout<<ans[2*i]<<endl;}
        return 0;
    }
    Tarjan LCA (s_a_b_e_r)

    by:wypx

  • 相关阅读:
    GDI+ 支持的图片文件格式
    Linux学习-灾难复原的考虑
    Linux学习-备份策略
    Linux学习-备份的种类、频率与工具的选择
    Linux学习-备份要点
    Linux学习-服务器硬件数据的收集
    Linux学习-系统基本设定
    Linux学习-开机过程的问题解决
    Linux学习-Boot Loader: Grub2
    Linux学习-核心与核心模块
  • 原文地址:https://www.cnblogs.com/ck666/p/7482826.html
Copyright © 2011-2022 走看看