Evanyou Blog 彩带

树的直径

传送门啦

思路:

dfs做法:

详细地说,这个做法包含两步:
1.从任意节点出发,通过 $ DFS $ 对树进行一次遍历,求出与出发点距离最远的节点记为 $ p $
2.从节点 $ p $ 出发,通过 $ DFS $再进行一次遍历,求出与 $ p $ 距离最远的节点,记为 $ q $ 。
从 $ p $ 到 $ q $ 的路径就是树的一条直径。因为 $ p $ 一定是直径的一端,否则总能找到一条更长的链,与直径的定义矛盾。 $ p $ 为直径的一端,那么自然的,与 $ p $ 最远的 $ q $ 就是直径的另一端。
在第2步的遍历中,可以记录下来每个点第一次被访问的前驱节点。最后从 $ q $ 递归到 $ p $ ,即可得到直径的具体方案
(代码中是从一号点出发找到 $ pos $ ,再从 $ pos $ 访问到1)

#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 , q , u , v , 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] ;

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 = 18 ; i >= 0 ; -- i) {
		if((1 << i) <= (dep[a] - dep[b])) {
			a = f[a][i] ;
		}
	}
	if(a == b)  return a ;
	for(re int i = 18 ; 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 () ; q = read () ;
	for(re int i = 1 ; i <= n - 1 ; ++ i) {
		u = read () ; v = read () ;
		add(u , v) ;
		add(v , u) ;
	}
	dfs(1 , 1) ; 
	for(re int i = 1 ; i <= q ; ++ i) {
		a = read () ; b = read () ; c = read () ; d = read () ;
		int fm1 = max(dep[lca(a , b)] , dep[lca(c , d)]) ;
		int fm2 = max(max(dep[lca(a , c)] , dep[lca(a , d)]) , max(dep[lca(b , c)] , dep[lca(b , d)])) ;
        if(fm2 >= fm1)
			printf("Y\n");
        else
    		printf("N\n");
	}
	return 0 ;
}
posted @ 2019-02-26 21:53  Stephen_F  阅读(192)  评论(0编辑  收藏  举报