zoukankan      html  css  js  c++  java
  • 洛谷P3379倍增LCA

    传送门

    #include <iostream> 
    #include <cstdio>
    #include <cstring>
    #include <cmath>
    #include <algorithm>
    #define re register
    using namespace std ;
    const int maxn = 5 * 1e5 + 4 ;
    
    inline int read () {
    	int f = 1 , x = 0 ;
    	char ch = getchar () ;
    	while (ch > '9' || ch < '0') {if(ch == '-') f = -1 ; ch = getchar () ;}
    	while (ch >= '0' && ch <= '9') {x = (x << 1) + (x << 3) + ch - '0' ; ch = getchar () ;}
    	return x * f ;
    }
    
    int n , m , s , x , y , a , b , c , d ;
    int head[maxn] , tot ;
    
    struct Edge {
    	int from , to , next ;
    }edge[maxn << 1] ;
    
    inline void add (int u , int v) {
    	edge[++tot].from = u ;
    	edge[tot].to = v ;
    	edge[tot].next = head[u] ;
    	head[u] = tot ;
    }
    
    int dep[maxn] , f[maxn][21] ;
    /*
    	dep数组用来记录当前点的深度
    	f[i][j]代表距离i 2^j的祖先
    */
    
    inline void dfs (int x , int fa) {
    	dep[x] = dep[fa] + 1 ;//更新深度
    	f[x][0] = fa ;//更新父亲结点
    	for(re int i = 1 ; (1 << i) <= dep[x] ; ++ i) 
    	//预处理出f数组
    		f[x][i] = f[f[x][i - 1]][i - 1] ;
    		//x的2^i级祖先 就是 x的2^(i-1)级祖先的2^(i-1)级祖先。
    	for(re int i = head[x] ; i ; i = edge[i].next) {
    		int v = edge[i].to ;
    		if(v != fa) dfs(v , x) ;
    		//如果v是x的父亲,那么就说明这条边被访问过了,不能再回溯了
    	}
    }
    
    inline int lca (int a , int b) {
    	if(dep[a] < dep[b])  swap(a , b) ;//让a的深度更深
    	for(re int i = 18 ; i >= 0 ; -- i) { //让a跳到跟b相同高度上
    		if((1 << i) <= (dep[a] - dep[b])) {
    			a = f[a][i] ;
    		}
    	}
    	if(a == b)  return a ; //a,b在同一枝上时,此时a,b会在同一位置,返回任意一个 
    	for(re int i = 18 ; i >= 0 ; -- i) { //从大到小跳
    		if((1 << i) <= dep[a] && (f[a][i] != f[b][i])) {
    			//如果不相等,就说明该节点的深度还是比LCA大
    			a = f[a][i] ;
    			b = f[b][i] ;
    			//继续跳
    		}
    	}
    	return f[a][0] ;
    	//此时a和b不是同一个节点,但是a和b的父亲就是a和b的lca。
    }
    
    int main () {
    	n = read () ; m = read () ; s = read () ; 
    	for(re int i = 1 ; i <= n - 1 ; ++ i) {
    		x = read () ; y = read () ;
    		add(x , y) ;
    		add(y , x) ;
    	}
    	dfs(s , 0) ;
    	while(m--) {
    		a = read () ; b = read () ;
    		printf("%d
    " , lca(a , b)) ;
    	}
    	return 0 ;
    }
    
  • 相关阅读:
    济南学习 Day2 T1 am
    济南学习 Day1 T2 pm
    济南学习 Day1 T3 am
    济南学习 Day 1 T2 am
    洛谷 P1209 修理牛棚== Codevs 2079 修理牛棚
    2016.10.30 济南学习 Day2 下午 T1
    餐厅随笔----2016.10.30 于济南 外出学习
    bzoj1671 [Usaco2005 Dec]Knights of Ni 骑士
    bzoj1088 [SCOI2005]扫雷Mine
    bzoj1655 [Usaco2006 Jan] Dollar Dayz 奶牛商店
  • 原文地址:https://www.cnblogs.com/Stephen-F/p/9933315.html
Copyright © 2011-2022 走看看