• LCA(离线算法)


    hdu4547

    CD操作

    Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others)
    Total Submission(s): 1010    Accepted Submission(s): 275


    Problem Description
      在Windows下我们可以通过cmd运行DOS的部分功能,其中CD是一条很有意思的命令,通过CD操作,我们可以改变当前目录。
      这里我们简化一下问题,假设只有一个根目录,CD操作也只有两种方式:
      
      1. CD 当前目录名...目标目录名 (中间可以包含若干目录,保证目标目录通过绝对路径可达)
      2. CD .. (返回当前目录的上级目录)
      
      现在给出当前目录和一个目标目录,请问最少需要几次CD操作才能将当前目录变成目标目录?
     

    Input
    输入数据第一行包含一个整数T(T<=20),表示样例个数;
    每个样例首先一行是两个整数N和M(1<=N,M<=100000),表示有N个目录和M个询问;
    接下来N-1行每行两个目录名A B(目录名是只含有数字或字母,长度小于40的字符串),表示A的父目录是B。
    最后M行每行两个目录名A B,表示询问将当前目录从A变成B最少要多少次CD操作。
    数据保证合法,一定存在一个根目录,每个目录都能从根目录访问到。
     

    Output
    请输出每次询问的结果,每个查询的输出占一行。
     

    Sample Input
    2 3 1 B A C A B C 3 2 B A C B A C C A
     

    Sample Output
    2 1 2
     

    方法一:

    1700ms

    #include"stdio.h"
    #include"string.h"
    #include"stdlib.h"
    #define M 100009
    #include"string"
    #include"map"
    #include"iostream"
    using namespace std;
    typedef struct st
    {
        int u,v,next,w;
    }E[M*3];
    E edge,edge1;
    int dis[M],head[M],head1[M],t,t1,use[M],in[M];
    int f[M];
    int finde(int x)
    {
        if(x!=f[x])
            f[x]=finde(f[x]);
        return f[x];
    }
    void make(int u,int v)
    {
        int x=finde(u);
        int y=finde(v);
        if(x!=y)
            f[x]=y;
    }
    void init()
    {
        t=t1=0;
        memset(head,-1,sizeof(head));
        memset(head1,-1,sizeof(head1));
    }
    void add(int u,int v)
    {
        edge[t].u=u;
        edge[t].v=v;
        edge[t].next=head[u];
        head[u]=t++;
    }
    void add1(int u,int v,int w)
    {
        edge1[t1].u=u;
        edge1[t1].v=v;
        edge1[t1].w=w;
        edge1[t1].next=head1[u];
        head1[u]=t1++;
    }
    void dfs(int u)
    {
        use[u]=1;
        int i;
        for(i=head[u];i!=-1;i=edge[i].next)
        {
            int v=edge[i].v;
            if(!use[v])
            {
                dis[v]=dis[u]+1;
                dfs(v);
                f[v]=u;
                make(u,v);
            }
        }
        for(i=head1[u];i!=-1;i=edge1[i].next)
        {
            int v=edge1[i].v;
            if(use[v])
            {
                edge1[i].w=edge1[i^1].w=f[finde(v)];
            }
        }
    }
    int main()
    {
        int T,i,m,n,x,y;
        char ch1[60],ch2[60];
        scanf("%d",&T);
        while(T--)
        {
            scanf("%d%d",&n,&m);
            map<string,int>mp;
            int k=1;
            init();
            memset(in,0,sizeof(in));
            for(i=1;i<n;i++)
            {
                scanf("%s%s",ch1,ch2);
                if(mp[ch1]==0)
                {
                    x=k;
                    mp[ch1]=k++;
                }
                else
                    x=mp[ch1];
                if(mp[ch2]==0)
                {
                    y=k;
                    mp[ch2]=k++;
                }
                else
                    y=mp[ch2];
                add(y,x);
                in[x]++;
            }
            while(m--)
            {
                scanf("%s%s",ch1,ch2);
                add1(mp[ch1],mp[ch2],0);
                add1(mp[ch2],mp[ch1],0);
            }
            memset(use,0,sizeof(use));
            memset(dis,0,sizeof(dis));
            for(i=1;i<=n;i++)
                f[i]=i;
            for(i=1;i<=n;i++)
            {
                if(!in[i])
                    dfs(i);
            }
            for(i=0;i<t1;i+=2)
            {
                int u=edge1[i].u;
                int v=edge1[i].v;
                int mid=edge1[i].w;
                int p;
                if(v==mid)
                    p=0;
                else
                    p=1;
                printf("%d
    ",dis[u]-dis[mid]+p);
            }
        }
    }
    方法二:

    2700ms

    #include"stdio.h"
    #include"string.h"
    #include"map"
    #include"iostream"
    #include"queue"
    using namespace std;
    #define M 100006
    int dis[M];
    int pre[M];
    int rank[M],use[M],t,head[M];
    int targan(int a,int b)
    {
        if(a==b)
            return a;
        else if(rank[a]>rank[b])
            return targan(pre[a],b);
        else
            return targan(a,pre[b]);
    }
    struct st
    {
        int u,v,next;
    }edge[M*3];
    void init()
    {
        t=0;
        memset(head,-1,sizeof(head));
    
    }
    void add(int u,int v)
    {
        edge[t].u=u;
        edge[t].v=v;
        edge[t].next=head[u];
        head[u]=t++;
    }
    void bfs(int s)
    {
        queue<int>q;
        memset(use,0,sizeof(use));
        use[s]=1;
        memset(rank,0,sizeof(rank));
        q.push(s);
        while(!q.empty())
        {
            int u=q.front();
            q.pop();
            for(int i=head[u];i!=-1;i=edge[i].next)
            {
                int v=edge[i].v;
                if(!use[v])
                {
                    use[v]=1;
                    rank[v]=rank[u]+1;
                    q.push(v);
                }
            }
        }
    }
    int main()
    {
        int w;
        scanf("%d",&w);
        while(w--)
        {
            map<string,int>mp;
            int n,m,i;
            char ch1[444],ch2[444];
            init();
            scanf("%d%d",&n,&m);
            for(i=1;i<=n;i++)
                pre[i]=i;
            int t=1;
            for(i=1;i<n;i++)
            {
                scanf("%s%s",ch1,ch2);
                if(!mp[ch1])
                    mp[ch1]=t++;
                if(!mp[ch2])
                    mp[ch2]=t++;
                pre[mp[ch1]]=mp[ch2];
                dis[mp[ch1]]=1;
                add(mp[ch2],mp[ch1]);
            }
            int tep=-1;
            for(i=1;i<=n;i++)
                if(pre[i]==i)
                tep=i;
            bfs(tep);
            while(m--)
            {
                scanf("%s%s",ch1,ch2);
                int ans=targan(mp[ch1],mp[ch2]);
                if(ans!=mp[ch2])
                    printf("%d
    ",rank[mp[ch1]]-rank[ans]+1);
                else
                    printf("%d
    ",rank[mp[ch1]]-rank[ans]);
            }
        }
        return 0;
    
    }



  • 相关阅读:
    Jmeter-日期格式转换为时间戳
    Java中异常的处理
    Java中接口的新特性,为接口添加静态方法和默认方法
    Java接口的应用之代理模式
    Java之接口(interface)的理解
    JAVA中使用super调用属性、方法、构造器
    JAVA方法的重写
    Java之方法
    Java之匿名对象
    关于多态性的使用
  • 原文地址:https://www.cnblogs.com/mypsq/p/4348248.html
Copyright © 2020-2023  润新知