zoukankan      html  css  js  c++  java
  • LCA回顾(主要针对倍增算法)

    这个有两种方法:

    一、倍增

    就是维护一个节点的第(2^0, 2^1, 2^2 ...)层父亲,这样的话我们在后面查询的时候就可以直接“跳”着找。

    void pushup()
    {
    	step=log(maxd*1.0)/log(2.0);
    
    	for(int i=1;i<=step;i++)
    		for(int p=1;p<=n;p++) if( fa[p][i-1] ) fa[p][i]=fa[ fa[p][i-1] ][i-1];
    
    	return;
    }
    

    然后查询的时候,先让两个点跳到同一深度

    所以要让较深的一个点先往上跳:

    if( dep[x]<dep[y] ) swap(x,y);
    for(int i=step;i>=0;i--) if( dep[x]-(1<<i)>=dep[y] ) x=fa[x][i];
    

    第二行相当于将(dep(x)-dep(y))的值做二进制拆分


    跳到同一深度之后,如果两个节点已经跳到同一个位置,就直接退出。

    否则,就要继续同时往上跳,但是,在跳的时候要保证:它们各自跳到的位置必须是不一样的!不然的话它们可能都跳到了(LCA)的上面!

    整个功能段见下(省略了建图部分):

    struct LCA
    {
    	int fa[maxn][22],dep[maxn];
    	int maxd;
    	
    	void dfs(int x,int f,int d)
    	{
    		fa[x][0]=f,dep[x]=d;
    		maxd=max( maxd,d );
    		
    		for(int i=G.Head[x];i;i=G.Next[i])
    		{
    			Graph::Edge e=G.edges[i];
    			if( e.to==f ) continue;
    			
    			dfs(e.to,x,d+1);
    		}
    		
    		return;
    	}
    	
    	int step;
    	
    	void pushup()
    	{
    		step=log(maxd*1.0)/log(2.0);
    		
    		for(int i=1;i<=step;i++)
    			for(int p=1;p<=n;p++) if( fa[p][i-1] ) fa[p][i]=fa[ fa[p][i-1] ][i-1];
    		
    		return;
    	}
    	
    	int LCA(int x,int y)
    	{
    		if( dep[x]<dep[y] ) swap(x,y);
    		
    		for(int i=step;i>=0;i--) if( dep[x]-(1<<i)>=dep[y] ) x=fa[x][i];
    		if( x==y ) return y;
    		
    		for(int i=step;i>=0;i--)
    			if( fa[x][i]!=fa[y][i] ) x=fa[x][i],y=fa[y][i];
    		
    		return fa[x][0];
    	}
    }SOL;
    

    二、树链剖分

    这个更简单,用(top)数组直接跳就行了……

  • 相关阅读:
    Docker-CentOS系统安装Docker
    Docker-准备Docker环境
    Docker系列-文章汇总
    商品订单库存一致性问题的思考
    java模板、工厂设计模式在项目中的重构
    2018Java年底总结
    java的AQS中enp没有同步代码块为啥是原子操作
    java使用awt包在生产环境docker部署时出现中文乱码的处理
    初探装饰器模式
    开灯问题
  • 原文地址:https://www.cnblogs.com/info---tion/p/11282987.html
Copyright © 2011-2022 走看看