zoukankan      html  css  js  c++  java
  • LCA的两种写法

    第一种是离线的Tarjan算法

    #include<cstdio>
    using namespace std;
    int rd(){
        int x=0,fl=1;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-'){fl=-1;}ch=getchar();}
        while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
        return fl*x;
    }
    int n,m,s,x,y,num1,num2;
    int f[500001],dis[500001],a[500001][3],hd1[500001],hd2[500001];
    bool vis[500001];
    struct star{int nt,to,ds;}e[1000001],e2[1000001];
    void add1(int from,int to){
        e[++num1].nt=hd1[from];
        e[num1].to=to;
        hd1[from]=num1;
    }
    void add2(int from,int to,int ds){
        e2[++num2].nt=hd2[from];
        e2[num2].to=to;
        e2[num2].ds=ds;
        hd2[from]=num2;
    }
    int find(int x){
        if(f[x]!=x)
            f[x]=find(f[x]);
        return f[x];
    }
    void un(int x,int y){
        int ra=find(x),rb=find(y);
        f[ra]=rb;
    }
    void tarjan(int x){
        vis[x]=1;
        for(int i=hd2[x];i;i=e2[i].nt){
            int to=e2[i].to,dis=e2[i].ds;
            if(vis[to]) 
                a[dis][2]=find(to);
        }
        for(int i=hd1[x];i;i=e[i].nt){
            int to=e[i].to;
            if(!vis[to]){
                tarjan(to);
                un(to,x);
            }
        }
    }
    int main(){
        n=rd();m=rd();s=rd();
        for(int i=1;i<n;i++){
            x=rd();y=rd();
            add1(x,y);add1(y,x);
        }
        for(int i=1;i<=m;i++){
            x=rd();y=rd();
            a[i][0]=x;a[i][1]=y;
            add2(x,y,i);add2(y,x,i);
        }
        for(int i=1;i<=n;i++)f[i]=i;
        tarjan(s);
        for(int i=1;i<=m;i++)
            printf("%d
    ",a[i][2]);
        return 0;
    }

    这个代码跑的飞快但是不太好理解。。

    还有一种用倍增的思想

    #include<iostream>
    #include<cstdio>
    using namespace std;
    int rd(){
        int x=0,fl=1;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-'){fl=-1;}ch=getchar();}
        while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
        return fl*x;
    }
    int n,m,x,y,s,num=0,hd[500100],dep[500100],f[500100][21];
    struct star{int nt,to;}e[1000100];
    void add(int fm,int to){e[++num].to=to;e[num].nt=hd[fm];hd[fm]=num;}
    void dfs(int x,int fa){
        dep[x]=dep[fa]+1;
        for(int i=1;i<=20;i++)
            f[x][i]=f[f[x][i-1]][i-1];
        for(int i=hd[x];i;i=e[i].nt)
        {
            int to=e[i].to;
            if(to==fa)continue;
            f[to][0]=x;
            dfs(to,x);
        }
    }
    int lca(int u,int v){
        if(dep[u]<dep[v])swap(u,v);
        for(int i=20;i>=0;i--){
            if(dep[f[u][i]]>=dep[v])
                u=f[u][i];
            if(u==v)return u;
        }
        for(int i=20;i>=0;i--)
            if(f[u][i]!=f[v][i]){
                u=f[u][i];v=f[v][i];
            }
        return f[u][0];
    }
    void print(int x){
        if(x<0){putchar('-');x=-x;}
        if(x>9)print(x/10);
        putchar(x%10+'0');
    }
    int main(){
        n=rd();m=rd();s=rd();
        for(int i=1;i<n;i++){
            x=rd();y=rd();
            add(x,y);add(y,x);
        }
        dfs(s,0);
        for(int i=1;i<=m;i++){
            x=rd();y=rd();
            print(lca(x,y));
            putchar('
    ');
        }
        return 0;
    }

    emmm....这种比较好理解但是跑的有点慢...

    如果不太懂...可以看这个/*                      */

    其实还有一种bfs版的玄学算法也安利一下

    /*                                                           */

  • 相关阅读:
    Linux GCC常用命令
    用两个栈实现一个队列(转载)
    BMP格式介绍(一)
    图像处理笔记(1): bmp文件结构处理与显示
    大数据竞赛平台——Kaggle 入门篇
    图像识别中的深度学习
    面向对象中的抽象和具体类的理解
    全排列算法
    少有程序员读的书
    照片回执
  • 原文地址:https://www.cnblogs.com/2017noipak/p/7783968.html
Copyright © 2011-2022 走看看