题目描述

小仓鼠的和他的基(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. 最短路径Floyd算法【图文详解】

    Floyd算法 1.定义概览 Floyd-Warshall算法(Floyd-Warshall algorithm)是解决任意两点间的最短路径的一种算法,可以正确处理有向图或负权的最短路径问题,同时也被 ...

  2. xshell连接ubuntu

    安装了 ubuntu-14 ,为了连接 xshell ,做出的一些配置如下: 1.激活root用户 sudo passwd root 设置新密码,设置成功后会有提示 passwd:password u ...

  3. Python: Pandas的DataFrame如何按指定list排序

    本文首发于微信公众号“Python数据之道”(ID:PyDataRoad) 前言 写这篇文章的起由是有一天微信上一位朋友问到一个问题,问题大体意思概述如下: 现在有一个pandas的Series和一个 ...

  4. MATLAB仿真中连续和离散的控制器有何区别?

    matlab系统同时提供连续和离散的控制器和对象的目的是:在降低用户使用复杂程度的同时提高仿真精度.仿真速度和应用的广泛性. 仿真步长和求解精度的概念对于理解这个问题至关重要. 首先是步长,步长和求解 ...

  5. 软件开发项目云端All-In-One体验

    如今在软件开发圈里混,Agile,DevOps,Cloud是大家经常挂在嘴边的词,其实大家各自都有在应用层上的经验,但是如何把三者很好的结合起来,这是所有项目管理者困惑和需要的问题. Agile让我们 ...

  6. Docker Machine 简介

    Docker Machine 是什么? Docker Machine 是 Docker 官方提供的一个工具,它可以帮助我们在远程的机器上安装 Docker,或者在虚拟机 host 上直接安装虚拟机并在 ...

  7. css透明度的设置

    Css代码 .transparent_class { filter:alpha(opacity=50); -moz-opacity:0.5; -khtml-opacity: 0.5; opacity: ...

  8. 实现简易版的moment.js

    github源码地址: www.baidu.com 作者: 易怜白 项目中使用了时间日期的处理方法,只使用了部分方法,为了不在引入第三方的库(moment.js),这里自己封装了项目中使用到的方法. ...

  9. 第13章 Linux的网络管理

    本文目录: 13.1 Linux数据包转发功能 13.2 和网络相关的几个文件说明 13.2.1 网卡配置文件ifcfg-* 13.2.2 DNS配置文件/etc/resolve.conf 13.2. ...

  10. 《HelloGitHub》第 15 期

    公告 这段时间没怎么写文章,跑去写 https://hellogithub.com 这个网站了,现在已经顺利上线,功能后面会持续迭代. 最后,这个 https://hellogithub.com 网站 ...