• 【洛谷】【lca+结论】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”。

    输入样例#15 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
    输入输出样例

    【算法分析:】

    对于四个点a, b, c, d,判断a->b, c->d这两条路径是否有重合的点,

    容易想到分别求出(a, b), (c, d)的最近公共祖先,只要其中一个点对的lca在另一个点对的最短路径上,则这两条路径相交.

    那如何判断lca与路径的位置关系呢?

    首先想到树上差分,但每次O(n)维护一个前缀和肯定会超时,弃掉.

    我们通过模拟可以得出这样的结论

     若一个点x在路径s->t上,则:

    1.   deep[x] ≥ deep[lca(s, t)]
    2.   lca(x, s) = x 或 lca(x, t) = x

    对于结论1.,由于x可以是lca(a, b)和lca(c, d)中的任意一个,所以自然是选择深度大的lca作为x

    对于结论2.,选定了x之后只需两个判断即可.

    【代码:】

     1 //仓鼠找sugar
     2 #include<iostream>
     3 #include<cstdio>
     4 #include<cstring>
     5 using namespace std;
     6 
     7 const int MAXN = 100000 + 1;
     8 const int K = 17 + 1;
     9 
    10 int n, Q;
    11 int deep[MAXN], f[MAXN][K];
    12 int edge_num, head[MAXN];
    13 struct Edge {
    14     int to, nxt;
    15 }h[MAXN << 1];
    16 
    17 inline int read() {
    18     int x = 0, f = 1; char ch = getchar();
    19     while(ch<'0' || ch>'9') {
    20         if(ch == '-') f = -1;
    21         ch = getchar();
    22     }
    23     while(ch>='0' && ch<='9')
    24         x = (x<<3) + (x<<1) + ch-48, ch = getchar();
    25     return x * f;
    26 }
    27 
    28 inline void Add(int from, int to) {
    29     h[++edge_num].to = to;
    30     h[edge_num].nxt = head[from];
    31     head[from] = edge_num;
    32 }
    33 
    34 inline void build(int u) {
    35     for(int i=head[u]; i!=-1; i=h[i].nxt) {
    36         if(!deep[h[i].to]) {
    37             deep[h[i].to] = deep[u] + 1;
    38             f[h[i].to][0] = u;
    39             build(h[i].to);
    40         }
    41     }
    42 }
    43 
    44 inline void fill() {
    45     for(int j=1; j<K; ++j)
    46     for(int i=1; i<=n; ++i)
    47         f[i][j] = f[f[i][j - 1]][j - 1];
    48 }
    49 
    50 inline int LCA(int a, int b) {
    51     if(deep[a] > deep[b]) swap(a, b);
    52     for(int i=K-1; i>=0; --i)
    53         if(deep[f[b][i]] >= deep[a]) b = f[b][i];
    54     if(a == b) return a;
    55     for(int i=K-1; i>=0; --i)
    56         if(f[a][i] != f[b][i])
    57             a = f[a][i], b = f[b][i];
    58     return f[b][0];
    59 }
    60 
    61 int main() {
    62     memset(head, -1, sizeof(head));
    63     n = read(), Q = read();
    64     for(int i=1; i<n; ++i) {
    65         int x = read(), y = read();
    66         Add(x, y), Add(y, x);
    67     }
    68     deep[1] = 1;
    69     build(1);
    70     fill();
    71     while(Q--) {
    72         int a = read(), b = read(), c = read(), d = read();
    73         int lca1 = LCA(a, b), lca2 = LCA(c, d);
    74         if(deep[lca1] > deep[lca2]) {
    75             swap(a, c); swap(b, d);
    76             swap(lca1, lca2);
    77         }
    78         if(LCA(lca2, a) == lca2 || LCA(lca2, b) == lca2) puts("Y");
    79         else puts("N");
    80     }
    81 }
  • 相关阅读:
    Odoo13_多选下拉框
    Odoo13_联动下拉框
    Odoo13_上传文件并指定保存到位置
    Flask_cookie和session
    云原生设计理念
    docker 清理掉none对象,未使用网络,缓存等命令
    解决ssh连接中断问题
    python更改程序运行目录为程序所在文件夹
    Vuejs Cron 表达式校验
    Kubernetes WebSocket: Error during WebSocket handshake: Unexpected response code: 403
  • 原文地址:https://www.cnblogs.com/devilk-sjj/p/9052696.html
Copyright © 2020-2023  润新知