仓鼠找 sugar

仓鼠找 sugar

输出格式

小仓鼠的和他的基(mei)友(zi)sugar 住在地下洞穴中,每个节点的编号为 \(1\sim n\)。地下洞穴是一个树形结构。这一天小仓鼠打算从从他的卧室(\(a\))到餐厅(\(b\)),而他的基友同时要从他的卧室(\(c\))到图书馆(\(d\))。他们都会走最短路径。现在小仓鼠希望知道,有没有可能在某个地方,可以碰到他的基友?

输出格式

第一行两个正整数 \(n\)\(q\),表示这棵树节点的个数和询问的个数。

接下来 \(n-1\) 行,每行两个正整数 \(u\)\(v\),表示节点 \(u\) 到节点 \(v\) 之间有一条边。

接下来 \(q\) 行,每行四个正整数 \(a\)\(b\)\(c\)\(d\),表示节点编号,也就是一次询问,其意义如上。

输出格式

对于每个询问,如果有公共点,输出大写字母 Y;否则输出N

\(100\%\) 的数据 \(1\le n, q\le10^5\)

思路

分析题目,其实就是让我们判断一棵树上 \(a \to b\) 的简单路径和 \(c \to d\) 的简单路径是否相交。

\(x \to y\) 简单路径的求法:求出 \(LCA(x,y)\),路径就是 \(x \to LCA(x,y) \to y\)

那么如何判断路径是否相交呢?

我们发现,\(LCA(a,b)\)\(LCA(c,d)\) 分别是两个路径上的‘最高点’。也就是说,我们只需要判断深度大的那个 \(LCA\) 值是否在另一条路径上就可以了。

题目转化成:求一个点是否在两个点的树上简单路径上。

时间复杂度 \(O(n\log n)\)

\(CODE\)

#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;
const int MAXN = 1e5 + 7;
const int LOG = 30;
int n,q;
int x,y;
int a,b,c,d;
int fa[MAXN][LOG];
vector<int> tree[MAXN];
int dep[MAXN];
void dfs(int pos,int f){//建树并预处理出深度等信息
	fa[pos][0] = f;
	dep[pos] = dep[f] + 1;
	for(int to : tree[pos]){
		if(to != f){
			dfs(to,pos);
		}
	}
}
int Lca(int x,int y){//倍增求LCA
	if(dep[y] > dep[x]) swap(x,y);
	int delta = dep[x] - dep[y];
	int cnt = 0;
	while(delta){
		if(delta & 1) x = fa[x][cnt];
		delta >>= 1;
		cnt++;
	}
	if(x == y) return x;
	for(int i = LOG - 2;i >= 0;i--){
		if(fa[x][i] != fa[y][i]){
			x = fa[x][i],y = fa[y][i];
		}
	}
	return fa[x][0];
}
int main(){
	ios::sync_with_stdio(false);
	cin.tie(0);
	cin>>n>>q;
	for(int i = 1;i < n;i++){
		cin>>x>>y;
		tree[x].push_back(y);
		tree[y].push_back(x);
	}
	dfs(1,0);
	for(int i = 1;i <= LOG - 2;i++){
		for(int j = 1;j <= n;j++){
			fa[j][i] = fa[fa[j][i - 1]][i - 1];
		}
	}
	for(int i = 1;i <= q;i++){
		cin>>a>>b>>c>>d;
		int lca1 = Lca(a,b);
		int lca2 = Lca(c,d);
		if(lca1 == lca2){
			cout<<"Y"<<endl;
			continue;
		}
		if(dep[lca2] > dep[lca1]) swap(lca1,lca2),swap(a,c),swap(b,d);
        //判断一个点是否在另外两个点的路径上
		int fst = Lca(lca1,c);
		int scd = Lca(lca1,d);
		if(dep[fst] == dep[lca1] || dep[lca1] == dep[scd]) cout<<"Y"<<endl;
		else cout<<"N"<<endl;
	}
	return 0;
}
posted @ 2024-09-27 21:10  wyl123ly  阅读(1)  评论(0编辑  收藏  举报