仓鼠找 sugar

仓鼠找 sugar

输出格式

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

输出格式

第一行两个正整数 nq,表示这棵树节点的个数和询问的个数。

接下来 n1 行,每行两个正整数 uv,表示节点 u 到节点 v 之间有一条边。

接下来 q 行,每行四个正整数 abcd,表示节点编号,也就是一次询问,其意义如上。

输出格式

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

100% 的数据 1n,q105

思路

分析题目,其实就是让我们判断一棵树上 ab 的简单路径和 cd 的简单路径是否相交。

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

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

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

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

时间复杂度 O(nlogn)

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 @   wyl123ly  阅读(8)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示