zoukankan      html  css  js  c++  java
  • 浅谈LCA

    什么是LCA

    LCA就是最近公共祖先

    对于有根树(Tree)的两个结点(u、v),最近公共祖先(LCA(T,u,v))表示一个结点(x),满足(x)(u、v)的祖先且(x)的深度尽可能大。

    倍增求LCA

    解释明天再写

    dfs

    #include<cstdio>
    #include<iostream>
    #include<cstring>
    using namespace std;
    const int maxn=500000+2;
    int n,m,root,k;
    int head[maxn],d[maxn];
    struct node {
    	int v,next;
    } e[maxn<<1];
    void add(int u,int v) {
    	e[k].v=v;
    	e[k].next=head[u];
    	head[u]=k++;
    }
    //________________________________________
    int f[maxn][21];
    void dfs(int u,int fa) {
    	d[u]=d[fa]+1;//更新深度,父亲的深度加1
    	f[u][0]=fa;//跳2^0步到爸爸
    	for(int i=1; (1<<i)/*即2^i*/<=d[u]; ++i) {
    		f[u][i]=f[f[u][i-1]][i-1];//敲黑板,看这里,解释放博客里面
    	}
    	for(int i=head[u]; i!=-1; i=e[i].next) {
    		int v=e[i].v;
    		if(v!=fa)//防止递归到爸爸
    			dfs(v,u);//递归下一层
    	}
    }
    int lca(int a,int b) {
    	if(d[a]>d[b]) swap(a,b);
    	for(int i=20; i>=0; --i) {
    		if(d[a]<=d[b]-(1<<i)) b=f[b][i];
    	}
    	if(a==b) return a;
    	for(int i=20; i>=0; --i) {
    		if(f[a][i]==f[b][i]) continue;
    		else a=f[a][i],b=f[b][i];
    	}
    	return f[a][0];
    }
    int main() {
    	memset(head,-1,sizeof(head));
    	cin>>n>>m>>root;
    	for(int i=1; i<n; ++i) {
    		int x,y;
    		scanf("%d%d",&x,&y);
    		add(x,y);
    		add(y,x);
    	}
    	dfs(root,0);
    	while(m--) {
    		int a,b;
    		scanf("%d%d",&a,&b);
    		cout<<lca(a,b)<<'
    ';
    	}
    	return 0;
    }
    

    bfs

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cmath>
    #include<queue>
    #include<stack>
    #include<vector>
    #include<map>
    #include<string>
    #include<cstring>
    using namespace std;
    inline int read() {
        char c = getchar();
        int x = 0, f = 1;
        while(c < '0' || c > '9') {
            if(c == '-') f = -1;
            c = getchar();
        }
        while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
        return x * f;
    }
    const int maxn=500005;
    const int inf=0x7fffffff;
    struct Edge {
        int ne,to;
    } edge[maxn<<1];
    int h[maxn],num_edge=0,t;
    inline void add_edge(int f,int to) {
        edge[++num_edge].ne=h[f];
        edge[num_edge].to=to;
        h[f]=num_edge;
        return ;
    }
    int f[maxn][35],d[maxn];
    int n,m,s;
    void bfs() {
        int u,v;
        memset(d,0,sizeof(d));
        queue <int>q;
        q.push(s);
        d[s]=1;
        while(q.size()) {
            u=q.front();
            q.pop();
            for(int  i=h[u]; i; i=edge[i].ne) {
                v=edge[i].to;
                if(d[v])continue;
                f[v][0]=u,d[v]=d[u]+1;
            
                for(int  j=1; j<=t; j++) {
                    f[v][j]=f[f[v][j-1]][j-1];
                }
                q.push(v);
            }
        }
        return ;
    }
    inline int lca(int x,int y) {
        if(d[x]<d[y])swap(x,y);
        if(x==y)return x;
        for(int  i=t; i>=0; i--) {
            if(d[f[x][i]]>=d[y])x=f[x][i];
        }
        if(x==y)return x;
        for(int i=t; i>=0; i--) {
            if(f[x][i]!=f[y][i])x=f[x][i],y=f[y][i];
        }
        return f[x][0];
    }
    int main() {
        int x,y,z;
        n=read(),m=read(),s=read();
        memset(f,0,sizeof(f));
        t=(int)(log(n)/log(2))+1;
        for(int  i=1; i<n; i++) {
            x=read();
            y=read();
            add_edge(x,y);
            add_edge(y,x);
        }
        bfs();
        for(int  i=1; i<=m; i++) {
                x=read();
            y=read();
            printf("%d
    ",lca(x,y));
        }
        return 0;
    }
    

    树剖求LCA

    解释同上以后再写

    
    // luogu-judger-enable-o2
    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cmath>
    #include<queue>
    #include<stack>
    #include<vector>
    #include<map>
    #include<string>
    #include<cstring>
    using namespace std;
    
    inline int read() {
        char c = getchar();
        int x = 0, f = 1;
        while(c < '0' || c > '9') {
            if(c == '-') f = -1;
            c = getchar();
        }
        while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
        return x * f;
    }
    const int N=500001;
    int n,m,root,cnt;
    struct node
    {
        int u,v,next;
    }e[N<<1];
    int head[N];
    int son[N];
    int f[N],d[N],s[N],c[N];
    void add(int x,int y)
    {
        e[++cnt].u=x;
        e[cnt].v=y;
        e[cnt].next=head[x];
        head[x]=cnt;
    }
    void dfs1(int n,int F)
    {
        s[n]=1;//初始化子树大小为1
        d[n]=d[F]+1;
        f[n]=F; 
        int V;
        for(int i=head[n];i;i=e[i].next)
        {
            V=e[i].v;
            if(V!=F)
            {
                dfs1(V,n);
                s[n]+=s[V];
                if(s[son[n]]<s[V]) son[n]=V;
            }
        }
    }
    void dfs2(int n,int C)
    {
        c[n]=C;
        if(son[n]) dfs2(son[n],C);
        else return;
        int V;
        for(int i=head[n];i;i=e[i].next)
        {
            V=e[i].v;
            if(V!=f[n] && V!=son[n]) dfs2(V,V);
        }
    }
    int lca(int x,int y)
    {
        for(;c[x]!=c[y];x=f[c[x]])
        {
            if(d[c[x]]<d[c[y]]) swap(x,y);
        }
        return d[x]<d[y]? x: y;
    }
    int main() 
    {
        n=read();m=read();root=read();
        for(int i=1;i<n;++i)
        {
            int x,y;
            x=read();
            y=read();
            add(x,y);
            add(y,x);	
        }
        dfs1(root,0);
        dfs2(root,root);
        for(int i=1;i<=m;++i)
        {
            int x,y;
            x=read();
            y=read();
            cout<<lca(x,y)<<'
    ';
        }
    }
    
  • 相关阅读:
    MariaDB的安装与启动
    Win10系统提示对于目标文件系统过大
    kvm中重命名虚拟机
    libvirt启动报错Failed to start Virtualization daemon
    常用的一些开源小工具 之 日期时间类
    常用的一些开源小工具 之 StringUtils
    zookeeper之 watch机制(三)
    shiro权限框架使用详解
    zookeeper节点之 java操作 和zookeeper-权限(ACL),设置超级用户(二)
    时间处理Date,最好改成 LocalDateTime ,时间计算,格式化时间,增加减少时间
  • 原文地址:https://www.cnblogs.com/pyyyyyy/p/11240533.html
Copyright © 2011-2022 走看看