• P3398 仓鼠找sugar(树链剖分)


    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

    分析

    设a,b的LCA是x,c,d的LCA是y。如果dep[x]>dep[y],x是较深的,如果c,d中一个,满足LCA(c/d,x)==x,就有交点。

    查找LCA,用树链剖分是可以的

    code

     1 #include<cstdio>
     2 #include<algorithm>
     3 #include<cstring>
     4 using namespace std;
     5 
     6 const int MAXN = 100100;
     7 struct Edge{
     8     int to,nxt;
     9 }e[MAXN<<1];
    10 int head[MAXN],dep[MAXN],top[MAXN],siz[MAXN],fa[MAXN],son[MAXN];
    11 int n,m,q,tot;
    12 
    13 void add(int u,int v)
    14 {
    15     ++tot;
    16     e[tot].to = v;
    17     e[tot].nxt = head[u];
    18     head[u] = tot;
    19 }
    20 void dfs1(int u,int f,int d)    //找重孩子 
    21 {
    22     dep[u] = d;
    23     fa[u] = f;
    24     siz[u] = 1;
    25     for (int i=head[u]; i; i=e[i].nxt)
    26     {
    27         int v = e[i].to;
    28         if (v!=f)
    29         {
    30             dfs1(v,u,d+1);
    31             siz[u] += siz[v];
    32             if (siz[v]>siz[son[u]])//son[]数组,用来保存重儿子
    33                 son[u] = v;
    34         }
    35     }
    36 }
    37 void dfs2(int x)    //找重链 
    38 {
    39     int t = 0;
    40     if (!top[x]) top[x] = x;
    41     for (int i=head[x]; i; i=e[i].nxt)
    42         if (fa[x]!=e[i].to&&siz[t]<siz[e[i].to]) 
    43             t = e[i].to;
    44     if (t) top[t] = top[x], dfs2(t);
    45     for (int i=head[x]; i; i=e[i].nxt)
    46         if(fa[x]!=e[i].to&&t!=e[i].to) dfs2(e[i].to);
    47 }
    48 
    49 int LCA(int x,int y)
    50 {
    51     while (top[x]!=top[y])
    52     {
    53         if (dep[top[x]]<dep[top[y]]) swap(x,y);
    54         x = fa[top[x]];
    55     }
    56     if(dep[x]>dep[y]) swap(x,y);
    57     return x;
    58 }
    59 int main()
    60 {
    61     scanf("%d%d",&n,&q);
    62     for (int x,y,i=1; i<n; ++i)
    63     {
    64         scanf("%d%d",&x,&y);
    65         add(x,y);add(y,x);
    66     }
    67     dfs1(1,0,1);
    68     dfs2(1);
    69     while (q--)
    70     {
    71         int a,b,c,d;
    72         scanf("%d%d%d%d",&a,&b,&c,&d);
    73         int tmp1 = LCA(a,b), tmp2 = LCA(c,d);
    74         if (dep[tmp1]<dep[tmp2]) swap(tmp1,tmp2),swap(a,c),swap(b,d);
    75         if (LCA(tmp1,c)==tmp1||LCA(tmp1,d)==tmp1) printf("Y
    ");
    76         else printf("N
    ");
    77     }
    78     return 0;
    79 }
  • 相关阅读:
    本周学习小结(04/11
    学习笔记之知识图谱 (Knowledge Graph)
    本周学习小结(28/10
    本周学习小结(21/10
    条件分页 代替离线查询
    Apache POI 一键上传(导入excel文件到数据库)
    easyui 菜单按钮&提示框
    Jquery ztree树插件
    Jquery ztree树插件2
    ui
  • 原文地址:https://www.cnblogs.com/mjtcn/p/7156939.html
Copyright © 2020-2023  润新知