当前位置:网站首页>洛谷 P3398 仓鼠找 sugar(树上倍增 lca 判断树中两条路径是否相交 结论)
洛谷 P3398 仓鼠找 sugar(树上倍增 lca 判断树中两条路径是否相交 结论)
2022-07-02 07:21:00 【Morgannr】
仓鼠找 sugar
题目描述
小仓鼠的和他的基(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
样例输入 #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
题意:
给定 n 个节点,节点之间总共连有 n - 1 条边,给出 最多 1e5 个询问,每个询问都判断 a ~ b 和 c ~ d 两条路径是否相交。相交输出 ‘Y’,否则 ‘N’。
思路:
多画几个图模拟一下,可以发现如下一个神奇的规律:
如果 a ~ b 和 c ~ d 两条路径相交,那么一定有 a ~ b 路径的 LCA 在 c ~ d 路径上,或者 c ~ d 路径的 LCA 在 a ~ b 路径上。
而 判断一个节点 x,是否在路径 s - t 上需要满足如下几个条件:(请记住,重要结论)
depth[x] >= depth[lca(s, t)] // x 位于 s、t 两点的 lca 相同高度或下方
lca(s, x) = x || lca(t, x) = x; // s、x 的 lca 是 x 或 t、x 的 lca 是 x
代码:
#define _CRT_SECURE_NO_WARNINGS 1
#include <bits/stdc++.h>
using namespace std;
//#define int long long
//#define map unordered_map
const int N = 1e5 + 10, M = N << 1;
int n, q;
int h[N], e[M], ne[M], idx;
int depth[N];
int fa[N][18];
void add(int a, int b)
{
e[idx] = b, ne[idx] = h[a], h[a] = idx++;
}
void bfs(int u)
{
queue<int> q; q.push(u);
while (q.size())
{
auto t = q.front(); q.pop();
for (int i = h[t]; ~i; i = ne[i])
{
int j = e[i];
if (depth[j] > depth[t] + 1)
{
depth[j] = depth[t] + 1;
q.push(j);
fa[j][0] = t;
for (int k = 1; k <= 17; ++k)
{
fa[j][k] = fa[fa[j][k - 1]][k - 1];
}
}
}
}
}
int lca(int a, int b)
{
if (depth[a] < depth[b]) swap(a, b);
for (int k = 17; k >= 0; --k)
{
if (depth[fa[a][k]] >= depth[b]) a = fa[a][k];
}
if (a == b) return a;
for (int k = 17; k >= 0; --k)
{
if (fa[a][k] != fa[b][k])
{
a = fa[a][k];
b = fa[b][k];
}
}
return fa[a][0];
}
void init(int root)
{
memset(depth, 0x3f, sizeof depth);
depth[0] = 0, depth[root] = 1;
bfs(root);
}
bool jud(int a, int b, int c, int d)
{
int p = lca(a, b);
if (depth[p] >= depth[lca(c, d)] && (lca(c, p) == p || lca(d, p) == p))
return true;
return false;
}
signed main()
{
int T = 1; //cin >> T;
while (T--)
{
memset(h, -1, sizeof h);
cin >> n >> q;
int t = n - 1;
int root = 0;
for (int i = 0; i < t; ++i)
{
int u, v; scanf("%d%d", &u, &v);
if (!i) root = u;
add(u, v), add(v, u);
}
init(root);
while (q--)
{
int a, b, c, d; scanf("%d%d%d%d", &a, &b, &c, &d);
if (jud(a, b, c, d) || jud(c, d, a, b))
{
puts("Y");
}
else puts("N");
}
}
return 0;
}
边栏推荐
猜你喜欢

Leetcode+ 76 - 80 storm search topic

VSCode工具使用

The nanny level tutorial of flutter environment configuration makes the doctor green to the end

Shutter - canvas custom graph

Ks009 implement pet management system based on SSH

Common methods of JS array

618 what is the secret of dominating the list again? Nike's latest financial report gives the answer

【快应用】text组件里的文字很多,旁边的div样式会被拉伸如何解决

14. Code implementation of semaphore

Dialogue Wu Gang: why do I believe in the rise of "big country brands"?
随机推荐
PCL 点云转深度图像
从.bag文件中读取并保存.jpg图片和.pcd点云
华为应用市场应用统计数据问题大揭秘
SPSS做Shapiro-Wilk正态分析
UWA report uses tips. Did you get it? (the fourth bullet)
Windows环境MySQL8忘记密码文件解决方案
The nanny level tutorial of flutter environment configuration makes the doctor green to the end
13.信号量临界区保护
长投学堂上面的账户安全吗?
AI技术产业热点分析
Internet News: Tencent conference application market was officially launched; Soul went to Hong Kong to submit the listing application
Thanos Receiver
如何使用IDE自动签名调试鸿蒙应用
华为AppLinking中统一链接的创建和使用
2. Hacking lab script off [detailed writeup]
洛谷 P5536 【XR-3】核心城市(贪心 + 树形 dp 寻找树的中心)
集成学习概览
二叉树专题--AcWing 3540. 二叉搜索树建树(实用板子 构建二叉搜索树 并输出前、中、后序遍历)
HDU1228 A + B(map映射)
Point cloud projection picture