zoukankan      html  css  js  c++  java
  • 树剖求lca

    算法分析

    用于求lca较广泛的算法大概就是倍增了,但倍增的常数较大,遇到一些毒

    瘤的题往往会被卡掉,这时,学会用树剖求lca就变得十分重要

    利用树剖求lca,我们首先需要对树进行剖分,剖分的方式任选,在这里我

    采取轻重链剖分,剖分完后,在询问两个点的lca,先判断两个点是否在同一

    重链上,假设在同一重链,此时深度较小的就是lca,假设不在同一重链

    我们对深度较大的点向上跳,跳到链顶的父亲,实现跨链操作,直到两点

    达到同一重链

    每次查询的时间复杂度为(O(long n))

    现在还是不清楚为什么按洛谷模板题的数据范围那么诡异

    按数据范围开反而炸了

    放代码吧

    这道题是洛谷的模板题

    这里

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<string>
    using namespace std;
    const int maxn=5e6+10;
    int n,m,s,l;
    inline int read(){
    	int ret=0;
    	int f=1;
    	char ch=getchar();
    	while(ch<'0'||ch>'9'){
    		if(ch=='-')
    			f=-f;
    		ch=getchar();
    	}
    	while(ch<='9'&&ch>='0'){
    		ret=ret*10+(ch^'0');
    		ch=getchar();
    	}
    	return ret*f;
    }
    struct node{
    	int nex;
    	int to;
    }e[maxn];
    int cnt;
    int head[maxn];
    int deep[maxn];
    void add(int u,int v){
    	cnt++;
    	e[cnt].nex=head[u];
    	e[cnt].to=v;
    	head[u]=cnt;
    }
    int son[maxn];
    int size[maxn];
    int fa[maxn];
    void dfs1(int x){
    	deep[x]=deep[fa[x]]+1;
    	size[x]=1;
    	for(int i=head[x];i;i=e[i].nex){
    		int y=e[i].to;
    		if(y!=fa[x]){
    			fa[y]=x;
    			dfs1(y);
    			size[x]+=size[y];
    			if(size[son[x]]<size[y]){
    				son[x]=y;//find the heavlial son
    			}
    		} 
    	}
    	return ;
    }
    int top[maxn];
    void dfs2(int x){
    	if(x==son[fa[x]]){
    		top[x]=top[fa[x]];
    	}
    	else 
    		top[x]=x;
    	for(int i=head[x];i;i=e[i].nex){
    		int y=e[i].to;
    		if(fa[y]==x){
    			dfs2(y);
    		}
    	}
    	return ;
    }
    void pre(int x){
    	dfs1(x);
    	dfs2(x);
    	return ;
    }
    int query(int u,int v){
        while(top[u]!=top[v])
        {
            if(deep[top[u]]>deep[top[v]])
                u=fa[top[u]];
            else
                v=fa[top[v]];
        }
        if(deep[u]<deep[v])
            return u;
        return v;
    }
    int main(){
    //	freopen("a.in","r",stdin);
    	n=read();
    	m=read();
    	s=read();
    	int x,y;
    	for(int i=1;i<=n-1;i++){
    		x=read();
    		y=read();
    		add(x,y);
    		add(y,x);
    	}
    	pre(s);
    	for(int i=1;i<=m;i++){
    		x=read();
    		y=read();
    		cout<<query(x,y)<<endl;
    	}
    	return 0;
    }
    
  • 相关阅读:
    day113-django-Form组件常用字段和参数
    day112-django-Form组件-ajax提交给后台的Form验证
    day110-django-中间件和(socket:wsgiref、uwsgi)
    day111-django-初识Form组件(验证登录信息)
    day109-django-多对多、session保存用户信息到数据库和从数据库获取用户信息
    day108-django-路由分发、动态路由、伪静态、根据名称反向生成url
    软件测试基础
    Python并发编程之:多进程
    进程介绍(理论部分)
    网络编程
  • 原文地址:https://www.cnblogs.com/rpup/p/13924357.html
Copyright © 2011-2022 走看看