zoukankan      html  css  js  c++  java
  • 洛谷 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,经过的深度最小的点为X 同理,C,D的为Y
    题目是一个点从A出发到B 一个从C出发到D
    那么从A到B可以分解成 先从A到X 再从X到B。。。 C同理
    假设能相遇 那么
    要么在A到X的过程A,B相遇 要么在X到B的过程A,B相遇
    对于在A到X的过程相遇的情况 又可以分解为:
    情况1:
    在A到X的过程和 C到Y的过程 中A,B相遇 此时相遇点的深度必然大于等于Max(X深度,Y深度)
    情况2:
    在A到X的过程和 Y到D的过程 中A,B相遇 此时相遇点的深度必然大于等于Max (X深度,Y深度)
    另一种情况同理。。。
    所以显然只要求出Max=max(lca(a,b),lca(c,d));(lca返回的是两个点公共祖先的最大深度
    假如lca(a,c) lca(a,d) lca(b,c) lca(b,d) 中有任意一个大于等于MIN 的话 那么可以相遇 否则不能

    以上部分思路转自 http://www.cnblogs.com/shenben/p/6066599.html

    屠龙宝刀点击就送

    #include <algorithm>
    #include <cstring>
    #include <cstdio>
    #define Max 100000
    using namespace std;
    
    struct Edge
    {
        int next,to;
    }edge[Max<<2];
    struct Point
    {
        int deep,size,fa,chain;
    }point[Max+1];
    int kk,head[Max<<2],cnt,n,q;
    void add(int u,int v)
    {
        cnt++;
        edge[cnt].next=head[u];
        edge[cnt].to=v;
        head[u]=cnt;
    }
    void dfs1(int now,int fa)
    {
        int pos=kk++;
        point[now].fa=fa;
        point[now].deep=point[point[now].fa].deep+1;
        for(int i=head[now];i;i=edge[i].next)
        {
            if(edge[i].to==fa) continue;
            dfs1(edge[i].to,now);
        }
        point[now].size=kk-pos;
    }
    void dfs2(int now,int chain)
    {
        int pos=0;
        point[now].chain=chain;
        for(int i=head[now];i;i=edge[i].next)
        {
            if(point[edge[i].to].chain) continue;
            if(point[pos].size<point[edge[i].to].size)
            pos=edge[i].to;
        }
        if(pos) dfs2(pos,chain);
        else return;
        for(int i=head[now];i;i=edge[i].next)
        {
            if(edge[i].to==point[now].fa||edge[i].to==pos) continue;
            dfs2(edge[i].to,edge[i].to);
        }
    }
    int lca(int x,int y)
    {
        while(point[x].chain!=point[y].chain)
        {
            if(point[point[x].chain].deep<point[point[y].chain].deep)
            swap(x,y);
            x=point[point[x].chain].fa;
        }
        return point[x].deep<point[y].deep?point[x].deep:point[y].deep;
    }
    int main()
    {
        scanf("%d%d",&n,&q);
        n--;
        for(int x,y;n--;)
        {
            scanf("%d%d",&x,&y);
            add(x,y);
            add(y,x);
        }
        dfs1(1,0);
        kk=0;
        dfs2(1,1);
        for(int Manx,a,b,c,d,e,f;q--;)
        {
            scanf("%d%d%d%d",&a,&b,&c,&d);
            Manx=max(lca(a,b),lca(c,d));
            if(lca(a,d)>=Manx||lca(c,b)>=Manx||lca(a,c)>=Manx||lca(b,d)>=Manx) printf("Y
    ");
            else printf("N
    ");
        }
        return 0;
    }
    我们都在命运之湖上荡舟划桨,波浪起伏着而我们无法逃脱孤航。但是假使我们迷失了方向,波浪将指引我们穿越另一天的曙光。
  • 相关阅读:
    Linux 学习 step by step (1)
    ubuntu server nginx 安装与配置
    ubuntu server samba服务器配置
    iOS app集成支付宝支付流程及后台php订单签名处理
    mac 连接windows 共享内容
    linux 文件查找,which,whereis,locate,find
    ubuntu server vsftpd 虚拟用户及目录
    ubuntu server 安装 mantis bug tracker 中文配置
    ubuntu server vsftpd 匿名用户上传下载及目录设置
    linux 用户管理,用户权限管理,用户组管理
  • 原文地址:https://www.cnblogs.com/ruojisun/p/6556854.html
Copyright © 2011-2022 走看看