当前位置:网站首页>洛谷 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;
}
边栏推荐
- Start class, data analysis, high salary training plan, elite class
- In the face of uncertainty, the role of supply chain
- 快应用中实现自定义抽屉组件
- JSP webshell免杀——JSP的基础
- 一招快速实现自定义快应用titlebar
- Kustomize使用手册
- 二叉树专题--P1030 [NOIP2001 普及组] 求先序排列
- 二叉树专题--洛谷 P1229 遍历问题(乘法原理 已知前、后序遍历求中序遍历个数)
- 洛谷 P4281 [AHOI2008]紧急集合 / 聚会(树上倍增 LCA)
- js promise.all
猜你喜欢
随机推荐
In the face of uncertainty, the role of supply chain
SPSS做Shapiro-Wilk正态分析
华为AppLinking中统一链接的创建和使用
UVM - usage of common TLM port
Internet News: Tencent conference application market was officially launched; Soul went to Hong Kong to submit the listing application
Sus system availability scale
618再次霸榜的秘密何在?耐克最新财报给出答案
二叉树专题--【深基16.例7】普通二叉树(简化版)(multiset 求前驱 后继 哨兵法)
js setTimeout()与面试题
UWA report uses tips. Did you get it? (the fourth bullet)
Jsp webshell Free from killing - The Foundation of JSP
Shutter - canvas custom graph
JS settimeout() and interview questions
Hdu1228 a + B (map mapping)
"Matching" is true love, a new attitude for young people to make friends
UVM - configuration mechanism
二叉树专题--AcWing 3540. 二叉搜索树建树(实用板子 构建二叉搜索树 并输出前、中、后序遍历)
static 函数中的静态变量
HDU1228 A + B(map映射)
【付费推广】常见问题合集,推荐榜单FAQ





![2. Hacking lab script off [detailed writeup]](/img/f3/29745761cd5ad4df84c78ac904ea51.png)


