题目描述

小仓鼠的和他的基(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”。

输入输出样例

输入样例#1:

5 5
2 5
4 2
1 3
1 4
5 1 5 1
2 2 1 4
4 1 3 4
3 1 1 5
3 5 1 4
输出样例#1:

Y
N
Y
Y
Y

说明

本题时限1s,内存限制128M,因新评测机速度较为接近NOIP评测机速度,请注意常数问题带来的影响。

20%的数据 n<=200,q<=200

40%的数据 n<=2000,q<=2000

70%的数据 n<=50000,q<=50000

100%的数据 n<=100000,q<=100000


My Solution

借用题解里沧澜的原话:

如果两条路径相交,那么一定有一条路径的LCA在另一条路径上

而判断一个节点x,是否在路径s-t上需要满足如下几个条件

    - deep[x]>=deep[LCA(s,t)]

    - LCA(s,x)=x或LCA(t,x)=x;

所以分两种情况讨论一下即可

剩下的就是lca模板了,找根我用了点分治里找重心

暂时只会倍增lca  QwQ

再犯sb错误,把&打成了&&

 #include<cstdio>
#include<cstring>
#include<iostream>
#include<vector>
using namespace std;
#define q1 first
#define q2 second
#define ss first
#define tt second inline int read(){
char ch;
int re=;
bool flag=;
while((ch=getchar())!='-'&&(ch<''||ch>''));
ch=='-'?flag=:re=ch-'';
while((ch=getchar())>=''&&ch<='') re=re*+ch-'';
return flag?-re:re;
} struct edge{
int to,next;
edge(int to=,int next=):
to(to),next(next){};
};
const int maxn=;
const int maxm=maxn<<;
const int maxlogn=;
typedef pair<int,int> PII;
typedef pair<PII,PII> PP;
int n,q;
vector<PP> ques;
int cnt=;
int head[maxn];
edge edges[maxm];
int root;
int F[maxn],son[maxn];
bool vis[maxn];
int depth[maxn],parent[maxlogn][maxn];
int sum; inline void add_edge(int from,int to){
edges[++cnt]=edge(to,head[from]);
head[from]=cnt;
edges[++cnt]=edge(from,head[to]);
head[to]=cnt;
} inline void add_ques(int a,int b,int c,int d){
ques.push_back(make_pair(make_pair(a,b),make_pair(c,d)));
} void getroot(int x,int fa){
son[x]=; F[x]=;
for(int ee=head[x];ee;ee=edges[ee].next)
if(edges[ee].to!=fa&&!vis[edges[ee].to]){
getroot(edges[ee].to,x);
son[x]+=son[edges[ee].to];
F[x]=max(F[x],son[edges[ee].to]);
}
F[x]=max(F[x],sum-son[x]);
if(F[x]<F[root]) root=x;
} void dfs(int v,int fa,int deep){
parent[][v]=fa;
depth[v]=deep;
for(int ee=head[v];ee;ee=edges[ee].next)
if(edges[ee].to!=fa) dfs(edges[ee].to,v,deep+);
} void init(){
memset(head,,sizeof head);
n=read(),q=read();
for(int i=;i<n-;i++){
int from=read(),to=read();
add_edge(from,to);
}
for(int i=;i<q;i++){
int a=read(),b=read(),c=read(),d=read();
add_ques(a,b,c,d);
}
memset(vis,,sizeof vis);
sum=F[root=]=n;
getroot(,);
dfs(root,-,);
for(int k=;k+<maxlogn;k++)
for(int v=;v<=n;v++)
if(parent[k][v]<) parent[k+][v]=-;
else parent[k+][v]=parent[k][parent[k][v]];
} int lca(int u,int v){
if(depth[u]>depth[v]) swap(u,v);
for(int k=;k<maxlogn;k++)
if(depth[v]-depth[u]>>k&)
v=parent[k][v];
if(u==v) return u;
for(int k=maxlogn-;k>=;k--)
if(parent[k][u]!=parent[k][v]){
u=parent[k][u];
v=parent[k][v];
}
return parent[][u];
} bool check(PP qu){
int lca1=lca(qu.q1.ss,qu.q1.tt),lca2=lca(qu.q2.ss,qu.q2.tt);
if(depth[lca1]>=depth[lca2]&&(lca1==lca(qu.q2.ss,lca1)||lca1==lca(qu.q2.tt,lca1)))
return ;
if(depth[lca2]>=depth[lca1]&&(lca2==lca(qu.q1.ss,lca2)||lca2==lca(qu.q1.tt,lca2)))
return ;
return ;
} void solve(){
for(int i=;i<q;i++)
if(check(ques[i])) puts("Y");
else puts("N");
} int main(){
//freopen("temp.in","r",stdin);
init();
solve();
return ;
}

就算孤岛已没有四季  也没人提及你的美丽  我还是要飞去那里

luogu P3398 仓鼠找sugar [LCA]的更多相关文章

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

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

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

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

  3. 【luogu P3398 仓鼠找sugar】 题解

    题目链接:https://www.luogu.org/problemnew/show/P3398 辣鸡树剖1300ms 倍增大法吼啊 #include <cstdio> #include ...

  4. P3398 仓鼠找sugar[LCA]

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

  5. Luogu P3398 仓鼠找sugar

    这还是一道比较好的树剖题(去你的树剖,LCA即可) 这里主要讲两种思路,其实都是很基本也很经典的 1 树链剖分 还是先讲一下这种算法吧,虽然写起来很烦(不过感觉写多了就习惯了,而且还有一种莫名的快感) ...

  6. p3398 仓鼠找sugar (LCA+讨论)

    分情况讨论,结果是两条路径有公共点时,深度大的LCA在另一条路径上且另一条路径的两个端点至少其中一个的与深度大的LCA的LCA为那个深度大的LCA #include <cstdio> #i ...

  7. P3398 仓鼠找sugar

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

  8. [Luogu 3398] 仓鼠找sugar

    [Luogu 3398] 仓鼠找sugar 又是 LCA- 前两天死活写不过的一个题今天终于顺手切了. 思路嘛参考了一楼题解. 就是说,对于 a, b, c, d 四个点, 令 x = LCA(a, ...

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

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

随机推荐

  1. Vue基础概念,学习环境等

    前提: 你已有 HTML.CSS 和 JavaScript 中级前端知识. 概念: Vue.js(读音 /vjuː/,类似于 view) 是一套构建用户界面的渐进式框架.与其他重量级框架不同的是,Vu ...

  2. iter迭代器的应用

    迭代器是访问集合元素的一种方式.迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束. 用户不用关心迭代器的内部结构,仅需通过next方法不断去读取下一个内容 不能随机访问任意一个内容,只 ...

  3. ThinkPHP 整合 PHPExcel ,数据导出功能实现,解决Invalid cell coordinate

    PHPExcel想必大家都不陌生,是用来操作Office Excel 文档的一个PHP类库,它基于微软的OpenXML标准和PHP语言.可以使用它来读取.写入不同格式的电子表格 本次只做数据导出功能的 ...

  4. 初步探究java中程序退出、GC垃圾回收时,socket tcp连接的行为

    初步探究java中程序退出.GC垃圾回收时,socket tcp连接的行为 今天在项目开发中需要用到socket tcp连接相关(作为tcp客户端),在思考中发觉需要理清socket主动.被动关闭时发 ...

  5. node.js如何制作命令行工具(一)

    之前使用过一些全局安装的NPM包,安装完之后,可以通过其提供的命令,完成一些任务.比如Fis3,可以通过fis3 server start 开启fis的静态文件服务,通过fis3 release开启文 ...

  6. 关于MATLAB处理大数据坐标文件201763

    目前已经找出26条特征 ,但是提交数据越来越少,给我的感觉是随机森林画的范围越来越小,输出的机器数据也越来越少,我自认为特征没太大问题 我已经将不懂之处列了出来,将于明天咨询大师级人物

  7. HBuilder使用方法

    /*注:本教程针对HBuilder5.0.0,制作日期2014-12-31*/创建HTML结构: h 8 (敲h激活代码块列表,按8选择第8个项目,即HTML代码块,或者敲h t Enter)中途换行 ...

  8. 【LeetCode】219. Contains Duplicate II

    题目: Given an array of integers and an integer k, find out whether there are two distinct indices i a ...

  9. 【Android Developers Training】 85. 不要有冗余的下载

    注:本文翻译自Google官方的Android Developers Training文档,译者技术一般,由于喜爱安卓而产生了翻译的念头,纯属个人兴趣爱好. 原文链接:http://developer ...

  10. 在MacOS中,Unity使用VSCode开发,4.7版本无法正常使用C#

    我在MacOS中安装了两个版本的Unity,一个是4.7版本,一个是5.6版本,在5.6版本中使用VSCode打开项目时,可以正常代码提示和查看,但是打开4.7版本的项目时,无法正常提示和查看. 经过 ...