【题目描述:】

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

小仓鼠那么弱,还要天天被zzq大爷虐,请你快来救救他吧!

【输入格式:】

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

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

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

【输出格式:】

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

输入样例#: 

输出样例#:
Y
N
Y
Y
Y

输入输出样例

【算法分析:】

对于四个点a, b, c, d,判断a->b, c->d这两条路径是否有重合的点,

容易想到分别求出(a, b), (c, d)的最近公共祖先,只要其中一个点对的lca在另一个点对的最短路径上,则这两条路径相交.

那如何判断lca与路径的位置关系呢?

首先想到树上差分,但每次O(n)维护一个前缀和肯定会超时,弃掉.

我们通过模拟可以得出这样的结论

 若一个点x在路径s->t上,则:

  1.   deep[x] ≥ deep[lca(s, t)]
  2.   lca(x, s) = x 或 lca(x, t) = x

对于结论1.,由于x可以是lca(a, b)和lca(c, d)中的任意一个,所以自然是选择深度大的lca作为x

对于结论2.,选定了x之后只需两个判断即可.

【代码:】

 //仓鼠找sugar
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std; const int MAXN = + ;
const int K = + ; int n, Q;
int deep[MAXN], f[MAXN][K];
int edge_num, head[MAXN];
struct Edge {
int to, nxt;
}h[MAXN << ]; inline int read() {
int x = , f = ; char ch = getchar();
while(ch<'' || ch>'') {
if(ch == '-') f = -;
ch = getchar();
}
while(ch>='' && ch<='')
x = (x<<) + (x<<) + ch-, ch = getchar();
return x * f;
} inline void Add(int from, int to) {
h[++edge_num].to = to;
h[edge_num].nxt = head[from];
head[from] = edge_num;
} inline void build(int u) {
for(int i=head[u]; i!=-; i=h[i].nxt) {
if(!deep[h[i].to]) {
deep[h[i].to] = deep[u] + ;
f[h[i].to][] = u;
build(h[i].to);
}
}
} inline void fill() {
for(int j=; j<K; ++j)
for(int i=; i<=n; ++i)
f[i][j] = f[f[i][j - ]][j - ];
} inline int LCA(int a, int b) {
if(deep[a] > deep[b]) swap(a, b);
for(int i=K-; i>=; --i)
if(deep[f[b][i]] >= deep[a]) b = f[b][i];
if(a == b) return a;
for(int i=K-; i>=; --i)
if(f[a][i] != f[b][i])
a = f[a][i], b = f[b][i];
return f[b][];
} int main() {
memset(head, -, sizeof(head));
n = read(), Q = read();
for(int i=; i<n; ++i) {
int x = read(), y = read();
Add(x, y), Add(y, x);
}
deep[] = ;
build();
fill();
while(Q--) {
int a = read(), b = read(), c = read(), d = read();
int lca1 = LCA(a, b), lca2 = LCA(c, d);
if(deep[lca1] > deep[lca2]) {
swap(a, c); swap(b, d);
swap(lca1, lca2);
}
if(LCA(lca2, a) == lca2 || LCA(lca2, b) == lca2) puts("Y");
else puts("N");
}
}

【洛谷】【lca+结论】P3398 仓鼠找sugar的更多相关文章

  1. 【树链剖分/倍增模板】【洛谷】3398:仓鼠找sugar

    P3398 仓鼠找sugar 题目描述 小仓鼠的和他的基(mei)友(zi)sugar住在地下洞穴中,每个节点的编号为1~n.地下洞穴是一个树形结构.这一天小仓鼠打算从从他的卧室(a)到餐厅(b),而 ...

  2. 洛谷 P3398 仓鼠找sugar 解题报告

    P3398 仓鼠找sugar 题目描述 小仓鼠的和他的基(mei)友(zi)sugar住在地下洞穴中,每个节点的编号为1~n.地下洞穴是一个树形结构.这一天小仓鼠打算从从他的卧室(a)到餐厅(b),而 ...

  3. P3398 仓鼠找sugar

    P3398 仓鼠找sugar 题目描述 小仓鼠的和他的基(mei)友(zi)sugar住在地下洞穴中,每个节点的编号为1~n.地下洞穴是一个树形结构.这一天小仓鼠打算从从他的卧室(a)到餐厅(b),而 ...

  4. P3398 仓鼠找sugar(树链剖分)

    P3398 仓鼠找sugar 题目描述 小仓鼠的和他的基(mei)友(zi)sugar住在地下洞穴中,每个节点的编号为1~n.地下洞穴是一个树形结构.这一天小仓鼠打算从从他的卧室(a)到餐厅(b),而 ...

  5. 洛谷P3398 仓鼠找sugar [LCA]

    题目传送门 仓鼠找sugar 题目描述 小仓鼠的和他的基(mei)友(zi)sugar住在地下洞穴中,每个节点的编号为1~n.地下洞穴是一个树形结构.这一天小仓鼠打算从从他的卧室(a)到餐厅(b),而 ...

  6. 洛谷 P3398 仓鼠找sugar 题解

    每日一题 day44 打卡 Analysis 首先有一个结论:先找 p1=(a,b),p2=(c,d) 的LCA的深度,在与(a,c),(a,d),(b,c),(b,d)中最深的LCA n的深度比较, ...

  7. luogu P3398 仓鼠找sugar [LCA]

    题目描述 小仓鼠的和他的基(mei)友(zi)sugar住在地下洞穴中,每个节点的编号为1~n.地下洞穴是一个树形结构.这一天小仓鼠打算从从他的卧室(a)到餐厅(b),而他的基友同时要从他的卧室(c) ...

  8. 洛谷10月月赛Round.1| P3398 仓鼠找sugar[LCA]

    题目描述 小仓鼠的和他的基(mei)友(zi)sugar住在地下洞穴中,每个节点的编号为1~n.地下洞穴是一个树形结构.这一天小仓鼠打算从从他的卧室(a)到餐厅(b),而他的基友同时要从他的卧室(c) ...

  9. 洛谷P3398 仓鼠找sugar

    题目描述 小仓鼠的和他的基(mei)友(zi)sugar住在地下洞穴中,每个节点的编号为1~n.地下洞穴是一个树形结构.这一天小仓鼠打算从从他的卧室(a)到餐厅(b),而他的基友同时要从他的卧室(c) ...

随机推荐

  1. thinkphp 查询单个“年-月-日” FROM_UNIXTIME

    *时间格式转换,使datetimepicker.js 能够搜索 查询 单个 年月日而不需是区间 查询. //另起一行看转换结果 select *,FROM_UNIXTIME(CreateTime,'% ...

  2. 面向对象(基础oop)之垃圾回收与静态成员

    大家好,我叫李京阳,,很高兴认识大家,之所以我想开一个自己的博客,就是来把自己所了解的知识点通过自己的话写一下,希望被博客园的朋友们点评和一起讨论一下,也希望从博客园中多认识一些软件开发人员!现在我开 ...

  3. shell与expect结合使用

    在linux操作系统下,使用脚本自动化,一般由两种方案,方案一:telnet+ftp,方案二:ssh+scp+expect. 以下主要使用ssh+scp+expect为例进行说明使用方式. 第一步:安 ...

  4. oracel存储过程编写 以及plsql存储过程的debug

    1.语法: create or replace procedure messagebackup_createTable       //此处存储过程名称不能超过30个字符 as  tableName ...

  5. 慕课网 jQuery 笔记

    $("div").html()是使用标签选择器获取div标签,对应于javascript中的各类选择器 $("*") ——所有元素 $("#lastn ...

  6. Android 应用安装

    DDMS下Files Explorer /data/app/xxx.apk 安装过程:1.拷贝文件xxx.apk到/data/app/xxx-1.apk 2.在/data/data目录下创建一个文件夹 ...

  7. OnCreateContextMenuListener接口简介

    OnCreateContextMenuListener接口是用来处理上下文菜单显示事件的监听接口.该方法是定义和注册上下文菜单的另一种方式.该接口中事件处理的回调方法签名如下所示. public vo ...

  8. 二、ionic如何使用外链

    1.ionic如何使用外链并返回原有页面? html如下: 对应的controller如下: (function() { angular.module('app').controller('extra ...

  9. ubuntu 下 mysql数据库的搭建 及 数据迁移

    1.mysql的安装 我是使用apt-get直接安装的 :sudo apt-get install mysql-server sudo apt-get install mysql-client 2.配 ...

  10. 【Kettle】3、数据源连接配置

    1.各系统版本信息 System:Windows旗舰版 Service Pack1 Kettle版本:6.1.0.1-196 JDK版本:1.8.0_72 2.连接介绍 关于Kettle数据源连接方式 ...