【洛谷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 ...
随机推荐
- protoc 命令参数
protoc 命令的获得 源码在 https://github.com/google/protobuf , 如果不想自己编译获得最新版本,则可以下载官方编译好的各个平台的,下载地址:https://g ...
- ubuntu下基于sqlite3后台的php环境的搭建
最近准备把公司的服务器换成linux 数据库sqlite3 搭建过程记录如下: 1 sqlite3安装.. apt-get install sqlite 2.PHP服务器搭建. apt-get ins ...
- Distributed Transaction Coordinator 无法启动
有时候我们需要进行COM应用程序的权限设置,控制面板-->管理工具-->组件服务-->然后依此展开:组件服务-->计算机-->我的电脑-->DCOM 配置,接下来找 ...
- review过去的10年
本科毕业有10个年头多了,如果对我的博客做一个主题分析,还真能发现一些规律,这里总结一下: 1. 活跃度 本科毕业最后一学期是思维最活跃的阶段,人生面临很多的变化和挑战,心态相对还不错. 从来北京以 ...
- java基础回顾(八)——Queue
今天回顾了下关于Queue的一些相关知识 我们可以看到,Deque也是一个接口,它继承了Queue的接口规范.其中LinkedList和ArrayDeque都是实现Deque接口,所以,可以说他们俩都 ...
- mac配置vim-go
基本的设置信息(参考网址:http://hessian.cn/p/1026.html): "还是配置/.vimrc文件. syn on "语法支持 set laststatus=2 ...
- margin:0 auto在IE中失效的解决方案
转自:http://www.cnblogs.com/hongchenok/archive/2012/11/29/2795041.html 最近在开发项目的时候,发现在火狐浏览器中设置外容器margin ...
- Hue整合Sqoop报空指针异常的解决方法
hue是一个Apache基金会下的一个开源图形化管理工具,使用python语言开发,使用的框架是Django.而sqoop也是Apache的一个开源工具,是使用Java语言开发,主要用于进行hdfs和 ...
- 自己开发基于c#的垂直滚动条控件
由于Visual Studio工具箱中自带滚动条控件外观太老,而且没有颜色外观属性可设置. 所以自己就试着开发一个垂直的滚动条,它可以用来控制TextBox的滚动. 由于代码比较多,源文件已经打包到网 ...
- TIJ读书笔记04-方法重载
TIJ读书笔记04-方法重载 为什么会有方法重载 方法签名 如何区分重载 关于基本类型的重载 为什么会有方法重载 OOP的编程方式就是让程序的逻辑更加接近现实世界的逻辑. 而在现实世界中,自然语言本身 ...