【洛谷P3398】仓鼠找sugar
画个图就能多少看出些规律
证明借鉴一下大牛的题解:
设从A到B,经过的深度最小的点为X 同理,C,D的为Y
题目是一个点从A出发到B 一个从C出发到D
那么从A到B可以分解成 先从A到X 再从X到B。。。 C同理
假设能相遇 那么
要么在A到X的过程A,B相遇 要么在X到B的过程A,B相遇
对于在A到X的过程相遇的情况 又可以分解为:
情况1:
在A到X的过程和 C到Y的过程 中A,B相遇 此时相遇点的深度必然大于等于MIN(X深度,Y深度)
情况2:
在A到X的过程和 Y到D的过程 中A,B相遇 此时相遇点的深度必然大于等于MIN (X深度,Y深度)
另一种情况同理。。。
所以显然只要求出MIN=min(lca(a,b),lca(c,d));(lca返回的是两个点公共祖先的最大深度)
假如lca(a,c) lca(a,d) lca(b,c) lca(b,d) 中有任意一个大于等于MIN 的话 那么可以相遇 否则不能
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=,M=,p=;
int n,q,size,father[N][p+],head[M];
int nxt[M],son[M],deep[N];
int read(){
int sum=;
char ch=getchar();
while (ch<''||ch>'')
ch=getchar();
while (ch>=''&&ch<=''){
sum=sum*+ch-'';
ch=getchar();
}
return sum;
}
void uni(int x,int y){
size++;
nxt[size]=head[x];
head[x]=size;
son[size]=y;
}
void swap(int &a,int &b){
int tmp=a;
a=b;
b=tmp;
}
void dfs(int fa,int x){
for (int k=head[x];k;k=nxt[k]){
int y=son[k];
if (y==fa)
continue;
father[y][]=x;
deep[y]=deep[x]+;
dfs(x,y);
}
}
void pre(){
for (int j=;j<=p;j++)
for (int i=;i<=n;i++)
father[i][j]=father[father[i][j-]][j-];
}
int LCA(int x,int y){
if (deep[x]<deep[y])
swap(x,y);
int d=deep[x]-deep[y];
for (int j=p;j>=;j--)
if (d&(<<j))
x=father[x][j];
if (x==y)
return x;
for (int j=p;j>=;j--)
if (father[x][j]!=father[y][j]){
x=father[x][j];
y=father[y][j];
}
return father[x][];
}
int main(){
int u,v;
size=;
n=read();
q=read();
for (int i=;i<n;i++){
u=read();
v=read();
uni(u,v);
uni(v,u);
}
deep[]=;
for (int i=;i<=n;i++)
father[i][]=i;
dfs(,);
pre();
int a,b,c,d;
for (int i=;i<=q;i++){
a=read();
b=read();
c=read();
d=read();
int lca=max(deep[LCA(a,b)],deep[LCA(c,d)]);
int l1=max(deep[LCA(a,c)],deep[LCA(a,d)]);
int l2=max(deep[LCA(b,c)],deep[LCA(b,d)]);
if (max(l1,l2)>=lca)
printf("Y\n");
else
printf("N\n");
}
return ;
}
当然我们也可以判断一下最深的LCA是否在较浅的LCA路径之外
(比如lca_min=lca(a,b),则若deep[a]<lca_max&&deep[b]<lca_max(=lca(c,d))就在外面)
在外面肯定不能相遇
否则再判断一下它是否在其路径上
判断方法,,倍增跳点即可
#include<cstdio>
#include<cstring>
using namespace std;
const int N=,M=,p=;
int n,q,size,father[N][p+],head[M];
int nxt[M],son[M],deep[N];
int read(){
int sum=;
char ch=getchar();
while (ch<''||ch>'')
ch=getchar();
while (ch>=''&&ch<=''){
sum=sum*+ch-'';
ch=getchar();
}
return sum;
}
void uni(int x,int y){
size++;
nxt[size]=head[x];
head[x]=size;
son[size]=y;
}
void swap(int &a,int &b){
int tmp=a;
a=b;
b=tmp;
}
void dfs(int fa,int x){
for (int k=head[x];k;k=nxt[k]){
int y=son[k];
if (y==fa)
continue;
father[y][]=x;
deep[y]=deep[x]+;
dfs(x,y);
}
}
void pre(){
for (int j=;j<=p;j++)
for (int i=;i<=n;i++)
father[i][j]=father[father[i][j-]][j-];
}
int LCA(int x,int y){
if (deep[x]<deep[y])
swap(x,y);
int d=deep[x]-deep[y];
for (int j=p;j>=;j--)
if (d&(<<j))
x=father[x][j];
if (x==y)
return x;
for (int j=p;j>=;j--)
if (father[x][j]!=father[y][j]){
x=father[x][j];
y=father[y][j];
}
return father[x][];
}
int check(int x,int y){
for (int j=p;j>=;j--)
if (deep[father[x][j]]>=deep[y])
x=father[x][j];
if (x==y)
return ;
return ;
}//deep[x]>deep[y]
int main(){
int u,v;
size=;
n=read();
q=read();
for (int i=;i<n;i++){
u=read();
v=read();
uni(u,v);
uni(v,u);
}
deep[]=;
father[][]=;
dfs(,);
pre();
int a,b,c,d;
for (int i=;i<=q;i++){
a=read();
b=read();
c=read();
d=read();
int lcax=LCA(a,b);
int lcay=LCA(c,d);
if (deep[lcax]<deep[lcay]){
swap(lcax,lcay);
swap(a,c);
swap(b,d);
}//deep[lcax]>deep[lcay]
if (check(lcax,lcay)&&(check(c,lcax)||check(d,lcax)))
printf("Y\n");
else
printf("N\n");
}
return ;
}
最后想说…………LCA的pre()函数……j 如果打错从0循环的话会很GG……
因为它会WA……不一定是RE……
【洛谷P3398】仓鼠找sugar的更多相关文章
- 洛谷 P3398 仓鼠找sugar 解题报告
P3398 仓鼠找sugar 题目描述 小仓鼠的和他的基(mei)友(zi)sugar住在地下洞穴中,每个节点的编号为1~n.地下洞穴是一个树形结构.这一天小仓鼠打算从从他的卧室(a)到餐厅(b),而 ...
- 洛谷P3398 仓鼠找sugar [LCA]
题目传送门 仓鼠找sugar 题目描述 小仓鼠的和他的基(mei)友(zi)sugar住在地下洞穴中,每个节点的编号为1~n.地下洞穴是一个树形结构.这一天小仓鼠打算从从他的卧室(a)到餐厅(b),而 ...
- 洛谷P3398 仓鼠找sugar
题目描述 小仓鼠的和他的基(mei)友(zi)sugar住在地下洞穴中,每个节点的编号为1~n.地下洞穴是一个树形结构.这一天小仓鼠打算从从他的卧室(a)到餐厅(b),而他的基友同时要从他的卧室(c) ...
- 洛谷——P3398 仓鼠找sugar
https://www.luogu.org/problem/show?pid=3398#sub 题目描述 小仓鼠的和他的基(mei)友(zi)sugar住在地下洞穴中,每个节点的编号为1~n.地下洞穴 ...
- 洛谷 P3398 仓鼠找sugar —— 树链剖分
题目:https://www.luogu.org/problemnew/show/P3398 树链剖分一下,路径就变成线段树上的几个区间: 两条路径相交就是线段树上有区间相交,所以在相应位置打个标记, ...
- 洛谷 P3398 仓鼠找sugar 题解
每日一题 day44 打卡 Analysis 首先有一个结论:先找 p1=(a,b),p2=(c,d) 的LCA的深度,在与(a,c),(a,d),(b,c),(b,d)中最深的LCA n的深度比较, ...
- 洛谷 [P3398] 仓鼠找sugar
树剖求LCA 我们可以发现,两条路径ab,cd相交,当且仅当 dep[lca(a,b)]>=dep[lca(c,d)]&(lca(lca(a,b),c)==lca(a,b)||lca(l ...
- 洛谷P3412 仓鼠找$Sugar\ II$题解(期望+统计论?)
洛谷P3412 仓鼠找\(Sugar\ II\)题解(期望+统计论?) 标签:题解 阅读体验:https://zybuluo.com/Junlier/note/1327573 原题链接:洛谷P3412 ...
- 洛谷p3398仓鼠找suger题解
我现在爱死树链剖分了 题目 具体分析的话在洛谷blog里 这里只是想放一下改完之后的代码 多了一个son数组少了一个for 少了找size最大的儿子的for #include <cstdio&g ...
- 洛谷 3398 仓鼠找sugar——树链剖分
题目:https://www.luogu.org/problemnew/show/P3398 原来只要把值记录成第几次就行了. 别忘了while(top[a]!=top[b])之后还要走一步. #in ...
随机推荐
- 全面了解 Linux 服务器 - 3. 查看 Linux 服务器的硬盘使用情况
1)查看硬盘及分区信息 liuqian@ubuntu:~# fdisk -l ...... ...... Disk /dev/sda: 100 GiB, 107374182400 bytes, 209 ...
- visudo 使用摘记
1. sudo <command> 免输入密码.root 运行 visudo. 添加命令行:<username> <hostname>=NOPASSWD: & ...
- outlook找不到文件Outlook.pst 如何启动
首先注明:这种情况在控制面板-邮件 无法打开的情况下可以使用以下命令打开设置界面 解决方法: 1. 开始 –> 运行 –> cmd 2. 在DOS下,用CD 切换到 Outlook.ex ...
- python发邮件
# -*- coding:utf- -*- import smtplib,os,sys,string import mimetypes from email import Encoders from ...
- PHP基于数组的分页函数(核心函数array_slice())
关于数组的分页函数,用数组进行分页的好处是可以方便的进行联合多表查询,只需要将查询的结果放在数组中就可以了以下是数组分页的函数,函数page_array用于数组的分页,函数show_array用于分页 ...
- C# 分部类与分部方法
一.定义 分部方法是指能够使编码人员跨多个代码文件实现类型的语法.简而言之.它可以让我们在一个文件中构建方法原型,而在另一个文件中实现 使用分部方法和分部类需要使用关键词partial,且紧靠在cla ...
- MySQL_杭州北仓 12.3-12.7需求活动期间累计下单达到3天及以上的客户_20161212
#C025_02杭州北仓 12.3-12.7需求活动期间累计下单达到3天及以上的客户明细 SELECT d.*,CASE WHEN 下单天次>=3 THEN "下单超过3天" ...
- Hibernate框架概念
1.Hibernate是ORM框架,完成对象的持久化操作. 2.允许开发者采用面向对象的方式来操作数据库. 3.安装Hibernate的插件到Eclipse中来自动生成配置文件. 4.Hibernat ...
- win8自动升级win8.1后 wampserver无法启动
原因是升级时win8把其他的系统服务都给停止了. 解决办法是左键点击wamp的小图标,选择apache/mysql - service - 安装服务. 然后再选择启动服务,即可.
- 转Web安全测试之XSS
转http://www.cnblogs.com/TankXiao/archive/2012/03/21/2337194.html XSS 全称(Cross Site Scripting) 跨站脚本攻击 ...