P3398 仓鼠找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
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

#include<bits/stdc++.h>
using namespace std;
const int SIZE = 2e5 + 7;
int f[SIZE][20], d[SIZE];
int ver[SIZE], nex[SIZE], head[SIZE];
int n, m, tot, t;
void add(int x, int y) {
    ver[++tot] = y; nex[tot] = head[x]; head[x] = tot;
}
int q[SIZE];
void bfs() {
    int l = 0, r = 0;
    q[r++] = 1; d[1] = 1;
    while (l < r) {
        int x = q[l++];
        for (int i = head[x]; i; i = nex[i]) {
            int y = ver[i];
            if (d[y]) continue;
            d[y] = d[x] + 1;
            f[y][0] = x;
            for (int j = 1; j <= t; j++) {
                f[y][j] = f[f[y][j - 1]][j - 1];
            }
            q[r++] = y;
        }
    }
}
int lca(int x, int y) {
    if (d[x] > d[y]) swap(x, y);
    for (int i = t; i >= 0; i--) {
        if (d[f[y][i]] >= d[x]) y = f[y][i];
    }
    if (x == y) return x;
    for (int i = t; i >= 0; i--) {
        if (f[x][i] != f[y][i]) x = f[x][i], y = f[y][i];
    }
    return f[x][0];
}
int dis(int a, int b) {
    int fa = lca(a, b);
    return abs(d[fa] - d[a]) + abs(d[fa] - d[b]);
}
void solve() {
    int x, y, s, c;
    cin >> n >> m;
    t = log(n) / log(2) + 1;
    for (int i = 1; i < n; i++) {
        scanf("%d%d", &x, &y);
        add(x, y);
        add(y, x);
    }
    bfs();
    while (m--) {
        scanf("%d%d%d%d", &x, &y, &s, &c);
        int f1 = lca(x, y), f2 = lca(s, c);
      // 如果f2在x,y的路径上,则dis(x, f2) + dis(y, f2) = dis(x, y)
if (dis(x, f2) + dis(y, f2) == dis(x, y) || dis(s, f1) + dis(c, f1) == dis(s, c)) printf("Y\n"); else printf("N\n"); } } int main() { solve(); return 0; }
posted @ 2020-07-28 20:23  HighLights  阅读(152)  评论(0)    收藏  举报