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

    题解:

    哎,竟然把dep数组开成了bool数组,调试了一个多小时....

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    const int maxn=100000+5;
    inline int read()
    {
        int x=0,f=1; char ch=getchar();
        while(ch<'0'||ch>'9') {if(ch=='-')f=-1; ch=getchar();}
        while(ch>='0'&&ch<='9'){x=x*10+ch-'0'; ch=getchar();}
        return x*f;
    }
    int n,m,num;
    int head[maxn],f[maxn][20],dep[maxn];
    bool vis[maxn];
    struct node
    {
        int next,to;
    }e[maxn<<1];
    void add(int from,int to)
    {
        e[++num].next=head[from];
        e[num].to=to;
        head[from]=num;
    }
    void dfs(int x,int d)
    {
        vis[x]=1;dep[x]=d;
        for(int i=head[x];i;i=e[i].next)
        {
            int to=e[i].to;
            if(!vis[to])
            {
                f[to][0]=x;
                dfs(to,d+1);
            }
        }
    }
    int lca(int a,int b)
    {
        if(dep[a]<dep[b]){int t=a;a=b;b=t;}
        int d=dep[a]-dep[b];
        for(int i=0;i<=18;i++)
        if(d&(1<<i)) a=f[a][i];
        if(a==b) return a;
        for(int i=18;i>=0;i--)
        if(f[a][i]&&f[a][i]!=f[b][i]) 
        {
            a=f[a][i];
            b=f[b][i];
        }
        return f[a][0];
    }
    int main()
    {
        n=read();m=read();
        for(int i=1;i<n;i++)
        {
            int x,y;
            x=read();y=read();
            add(x,y);add(y,x);
        }
        dfs(1,1);
        for(int j=1;j<=18;j++)
        for(int i=1;i<=n;i++)
        f[i][j]=f[f[i][j-1]][j-1];
        for(int i=1;i<=m;i++)
        {
            int a,b,c,d,x,y;
            a=read();b=read();
            c=read();d=read();
            x=lca(a,b);y=lca(c,d);
            if(dep[x]==dep[y])
            {
                if(x==y) printf("Y
    ");
                else printf("N
    ");
            }
            else if(dep[x]>dep[y])
            {
                if(dep[c]<dep[x]&&dep[d]<dep[x])
                {printf("N
    ");continue;}
                if(lca(x,c)==x||lca(x,d)==x)
                printf("Y
    ");
                else printf("N
    ");
            }
            else if(dep[x]<dep[y])
            {
                if(dep[a]<dep[y]&&dep[b]<dep[y])
                {printf("N
    ");continue;}
                if(lca(y,a)==y||lca(y,b)==y)
                printf("Y
    ");
                else printf("N
    ");
            }
        }
        return 0;
    }            

     洛谷讨论里的另一种思路:https://www.luogu.org/discuss/show?postid=4783

    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #define maxn 100020
    using namespace std;
    int head[maxn*2],n,m,tot,h[maxn],f[maxn][18];
    struct edge{
        int v,next;
    }e[maxn*2];
    void adde(int a,int b){
        e[tot].v=b;
        e[tot].next=head[a];
        head[a]=tot++;
    }
    void dfs(int u,int fa){
        h[u]=h[fa]+1;f[u][0]=fa;
        for(int i=1;i<18;i++)f[u][i]=f[f[u][i-1]][i-1];
        for(int i=head[u];~i;i=e[i].next){
            int v=e[i].v;
            if(v==fa)continue;
            dfs(v,u);
        }
    }
    int lca(int a,int b){
        if(h[a]>h[b])swap(a,b);
        for(int i=17;i>=0;i--){
            if(h[f[b][i]]>=h[a])b=f[b][i];
        }
        if(a==b)return a;
        for(int i=17;i>=0;i--){
            if(f[a][i]==f[b][i])continue;
            a=f[a][i],b=f[b][i];
        }
        return f[a][0];
    }
    bool check(int a,int b){
        for(int i=17;i>=0;i--){
            if(h[f[b][i]]>=h[a])b=f[b][i];
        }
        return a==b;
    }
    int main(){
        memset(head,-1,sizeof(head));
        scanf("%d%d",&n,&m);
        for(int a,b,i=1;i<n;i++){
            scanf("%d%d",&a,&b);
            adde(a,b),adde(b,a);
        }
        dfs(1,1);
        int a,b,c,d,dx,dy;
        while(m--){
            scanf("%d%d%d%d",&a,&b,&c,&d);
            dx=lca(a,b);dy=lca(c,d);
            if(h[dx]>h[dy]){
                swap(dx,dy),swap(a,c),swap(b,d);
            }
            if(check(dx,dy)&&(check(dy,a)||check(dy,b)))printf("Y
    ");//需要判断三个 
            else printf("N
    ");
        }
        return 0;
    }
    View Code
  • 相关阅读:
    BZOJ 1101 莫比乌斯函数+分块
    BZOJ 2045 容斥原理
    BZOJ 4636 (动态开节点)线段树
    BZOJ 2005 容斥原理
    BZOJ 2190 欧拉函数
    BZOJ 2818 欧拉函数
    BZOJ 3123 主席树 启发式合并
    812. Largest Triangle Area
    805. Split Array With Same Average
    794. Valid Tic-Tac-Toe State
  • 原文地址:https://www.cnblogs.com/bahl/p/7260831.html
Copyright © 2011-2022 走看看