• 洛谷P4281 紧急会议


    传送门啦

    思路:

    $ Lca $ 这个题要求这个显而易见吧。但是难就难在怎么在树上利用 $ Lca $ 去解决三个点的问题。

    首先明确三个点两两的 三个 $ Lca $ 中有一对是相等的,我们也会发现这个相同的 $ Lca $ 肯定是深度最小的一个 $ Lca $ 。可以动手画一下图试试。

    同样也用了一下树上差分的知识。

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <cmath>
    #include <queue>
    #define re register
    using namespace std ;
    const int maxn = 500005 ;
    
    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 , u , v , a , b , c ;
    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] ;
    
    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[x][i] = f[f[x][i - 1]][i - 1] ;
    	}
    	for(re int i = head[x] ; i ; i = edge[i].next) {
    		int v = edge[i].to ;
    		if(v != fa)  dfs(v , x) ;
    	}
    }
    
    inline int lca(int a , int b) {
    	if(dep[a] < dep[b])  swap(a , b) ;
    	for(re int i = 20 ; i >= 0 ; -- i) {
    		if((1 << i) <= (dep[a] - dep[b])) {
    			a = f[a][i] ;
    		}
    	}
    	if(a == b)  return a ;
    	for(re int i = 20 ; i >= 0 ; -- i) {
    		if((1 << i) <= dep[a] && (f[a][i] != f[b][i])) {
    			a = f[a][i] ;
    			b = f[b][i] ;
    		}
    	}
    	return f[a][0] ;
    }
     
    int main () {
    	n = read () ; m = read () ;
    	for(re int i = 1 ; i <= n - 1 ; ++ i) {
    		u = read () ; v = read () ;
    		add(u , v) ;
    		add(v , u) ;
    	}
    	dfs(1 , 0) ;
    	for(re int i = 1 ; i <= m ; ++ i) {
    		a = read () ; b = read () ; c = read () ;
    		int root = 0 , ans = 0 ; 
    		int r1 = lca(a , b) ;
    		int r2 = lca(b , c) ;
    		int r3 = lca(a , c) ;
    		if(r1 == r2)  root = r3 ;
    		else if(r1 == r3)  root = r2 ;
    		else root = r1 ;
    		ans = dep[a] + dep[b] + dep[c] - dep[r1] - dep[r2] - dep[r3] ;
    		printf("%d %d
    " , root , ans) ;
    	}
    	return 0 ;
    }	
    
  • 相关阅读:
    测试sql语句性能,提高执行效率
    js积累
    如何提高AJAX客户端响应速度
    视频代码
    网页视频播放器收集
    WinForm软件开机自动启动详细方法
    JS时间格式化函数
    (转)CSS+DIV float 定位
    CSS+DIV 布局三种定位方式
    CSS+DIV布局初练—DIV元素必须成对出现?
  • 原文地址:https://www.cnblogs.com/Stephen-F/p/10453344.html
Copyright © 2020-2023  润新知