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
  • 相关阅读:
    HDU 5528 Count a * b 欧拉函数
    HDU 5534 Partial Tree 完全背包
    HDU 5536 Chip Factory Trie
    HDU 5510 Bazinga KMP
    HDU 4821 String 字符串哈希
    HDU 4814 Golden Radio Base 模拟
    LA 6538 Dinner Coming Soon DP
    HDU 4781 Assignment For Princess 构造
    LA 7056 Colorful Toy Polya定理
    LA 6540 Fibonacci Tree
  • 原文地址:https://www.cnblogs.com/bahl/p/7260831.html
Copyright © 2011-2022 走看看