zoukankan      html  css  js  c++  java
  • [Luogu 3398] 仓鼠找sugar

    [Luogu 3398] 仓鼠找sugar

    <题目链接>


    又是 LCA…

    前两天死活写不过的一个题今天终于顺手切了。

    思路嘛参考了一楼题解。

    就是说,对于 a, b, c, d 四个点,

    x = LCA(a, b), y = LCA(c, d),

    两条路径有交叉,当且仅当 c, d 至少一个在 x 的子树下,且 a, b 至少一个在 y 的子树下。

    由于我是 HLD 求的 LCA,第一遍 DFS 时顺手把子树大小求了,后边判断在不在一棵子属下的时候就可以很方便了。

    就这样。

    #include <algorithm>
    #include <cstdio>
    
    const int MAXN = 100010; 
    
    int n, q; 
    
    struct Graph
    {
        struct Edge
        {
            int to; 
            Edge *next; 
            Edge(int to, Edge* next): to(to), next(next) {}
            ~Edge(void)
            {
                if(next != NULL)
                    delete next; 
            }
        }*head[MAXN]; 
        Graph(int n)
        {
            std :: fill(head + 1, head + n + 1, (Edge*)NULL); 
        }
        ~Graph(void)
        {
            for(int i = 1; i <= n; ++i)
                delete head[i]; 
        }
        void AddEdges(int u, int v)
        {
            head[u] = new Edge(v, head[u]); 
            head[v] = new Edge(u, head[v]); 
        }
    }*G; 
    
    namespace HLD
    {
        int num; 
        struct Node
        {
            int depth, father, son, top, size, DFN; 
        }s[MAXN]; 
        void DFS1(int u, int k)
        {
            s[u].depth = k; 
            s[u].size = 1; 
            int v; 
            for(Graph :: Edge *i = G -> head[u]; i != NULL; i = i -> next)
                if(!s[v = i -> to].size)
                {
                    DFS1(v, k + 1); 
                    s[u].size += s[v].size; 
                    s[v].father = u; 
                    if(s[v].size > s[s[u].son].size)
                        s[u].son = v; 
                }
        }
        void DFS2(int u, int top)
        {
            s[u].top = top; 
            s[u].DFN = ++num; 
            if(s[u].son)
                DFS2(s[u].son, top); 
            int v; 
            for(Graph :: Edge *i = G -> head[u]; i != NULL; i = i -> next)
                if(!s[v = i -> to].DFN)
                    DFS2(v, v); 
        }
        void Init(void)
        {
            DFS1(1, 1); 
            DFS2(1, 1); 
        }
        int LCA(int x, int y)
        {
            int a, b; 
            while((a = s[x].top) ^ (b = s[y].top))
                if(s[a].depth > s[b].depth)
                    x = s[a].father; 
                else
                    y = s[b].father; 
            return s[x].depth < s[y].depth ? x : y; 
        }
        bool Range(int x, int y)
        {
            return s[x].DFN <= s[y].DFN && s[y].DFN < s[x].DFN + s[x].size; 
        }
        bool Query(int a, int b, int c, int d)
        {
            int x = LCA(a, b), y = LCA(c, d); 
            return (Range(x, c) || Range(x, d)) && (Range(y, a) || Range(y, b)); 
        }
    }
    
    int main(void)
    {
        scanf("%d %d", &n, &q); 
        G = new Graph(n); 
        for(int i = 1, u, v; i < n; ++i)
        {
            scanf("%d %d", &u, &v); 
            G -> AddEdges(u, v); 
        }
        HLD :: Init(); 
        for(int i = 1, a, b, c, d; i <= q; ++i)
        {
            scanf("%d %d %d %d", &a, &b, &c, &d); 
            puts(HLD :: Query(a, b, c, d) ? "Y" : "N"); 
        }
        return 0; 
    }
    

    谢谢阅读。

  • 相关阅读:
    获取文件夹下的所有文件名,并修改某些文件名 Alec
    生成XML文件,并保存到本地文件 Alec
    按Enter键起到Tab键的效果 Alec
    网站底部浮动js Alec
    NET Framework4.0注册 Alec
    从FTP上下载文件到本地 Alec
    生成txt日志操作文件 Alec
    不使用第三个变量,实现两个变量值的交换 Alec
    生成指定位数的回文素数 Alec
    单击gridview某一列弹出详细信息 Alec
  • 原文地址:https://www.cnblogs.com/Capella/p/9912634.html
Copyright © 2011-2022 走看看