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
  • 相关阅读:
    5359. 最大的团队表现值
    Trie树模板
    [NOIP 2009] 细胞分裂(选做)
    【SpringCloud】07.应用间的通信
    【SpringCloud】06.Eureka 总结
    【SpringCloud】05.Eureka的高可用
    【SpringCloud】04.SpringCloud Eureka Server与Client的创建
    【SpringCloud】03.微服务的设计原则
    【SpringCloud】02.微服务与SpringCloud
    【SpringCloud】01.常见软件架构的区别
  • 原文地址:https://www.cnblogs.com/bahl/p/7260831.html
Copyright © 2011-2022 走看看