zoukankan      html  css  js  c++  java
  • Hdu 4547 CD操作 LCA问题

    CD操作

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


    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
     

    Source
     

    Recommend
    liuyiding
     

    ----------------

    先求每个点的深度。

    再求出待询问两点间的最近公共祖先。

    第一次写lca问题,码略挫

    ----------------

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <map>
    
    using namespace std;
    
    const int maxn=411111;
    
    char name_x[1111];
    char name_y[1111];
    map<string,int>mp;
    
    struct ANS{
        int x;
        int y;
        int lca;
    }ans[maxn];
    
    int p[maxn];
    int head[maxn];
    int qhead[maxn];
    struct NODE{
        int to;
        int next;
        int num;
        int lca;
    };
    NODE edges[maxn];
    NODE qedges[maxn];
    int edge,qedge;
    
    void addedge(int u,int v)
    {
        edges[edge].to=v;edges[edge].next=head[u];head[u]=edge++;
    }
    void addqedge(int u,int v,int num)
    {
        qedges[qedge].num=num;
        qedges[qedge].to=v;qedges[qedge].next=qhead[u];qhead[u]=qedge++;
    }
    
    int find(int x)
    {
        if (p[x]!=x) p[x]=find(p[x]);
        return p[x];
    }
    
    bool visit[maxn];
    
    void LCA(int u)
    {
        p[u]=u;
        int k;
        visit[u]=true;
        for (k=head[u];k!=-1;k=edges[k].next)
        {
            if (!visit[edges[k].to])
            {
                LCA(edges[k].to);
                p[edges[k].to]=u;
            }
        }
        for (k=qhead[u];k!=-1;k=qedges[k].next)
        {
            if (visit[qedges[k].to])
            {
                qedges[k].lca=find(qedges[k].to);
                qedges[k^1].lca=qedges[k].lca;
                //cerr<<qedges[k].lca<<"---lca---"<<qedges[k].num<<endl;
                ans[qedges[k].num].lca=qedges[k].lca;
            }
        }
    }
    
    int ind[maxn];
    
    int dep[maxn];
    void dfs(int u,int pat,int deep)
    {
        int k;
        dep[u]=deep;
        for (k=head[u];k!=-1;k=edges[k].next)
        {
            if (edges[k].to!=pat)
            dfs(edges[k].to,u,deep+1);
        }
    }
    
    int main()
    {
        int T,n,m;
        int x,y;
        int cnt;
        int root;
        scanf("%d",&T);
        while (T--)
        {
            //初始化
            memset(head,-1,sizeof(head));
            memset(qhead,-1,sizeof(qhead));
            memset(edges,0,sizeof(edges));
            memset(qedges,0,sizeof(qedges));
            memset(ind,0,sizeof(ind));
            memset(dep,0,sizeof(dep));
            memset(visit,0,sizeof(visit));
            mp.clear();
            edge=0;
            qedge=0;
            cnt=1;
            //读入数据
            scanf("%d%d",&n,&m);
            for (int i=1;i<=n-1;i++)
            {
                scanf("%s%s",name_x,name_y);
                //映射
                if (mp[name_x]==0)
                {
                    x=cnt;
                    mp[name_x]=cnt++;
                }
                else
                {
                    x=mp[name_x];
                }
                if (mp[name_y]==0)
                {
                    y=cnt;
                    mp[name_y]=cnt++;
                }
                else
                {
                    y=mp[name_y];
                }
                //cerr<<"x y "<<x<<" "<<y<<endl;
                //添加边
                addedge(y,x);
                addedge(x,y);
                //计算入度
                ind[x]++;
            }
            //寻找根节点
            root=0;
            for (int i=1;i<cnt;i++)
            {
                if (ind[i]==0)
                {
                    root=i;
                }
            }
            //cerr<<root<<"root"<<endl;
            //读入待处理数据
            for (int i=1;i<=m;i++)
            {
                scanf("%s%s",name_x,name_y);
                x=mp[name_x];
                y=mp[name_y];
                //添加正反询问边
                addqedge(x,y,i);
                addqedge(y,x,i);
                ans[i].x=x;
                ans[i].y=y;
            }
            //寻找lca
            //cerr<<"aaaaaaaaaaaaaaaa"<<endl;
            LCA(root);
            //计算深度
            dfs(root,-1,1);
            //for (int i=1;i<=n;i++) cerr<<dep[i]<<endl;
            //处理询问
            //cerr<<"aaaaaaaaaaaaaaaa"<<endl;
            for (int i=1;i<=m;i++)
            {
                int as=0;
                as=dep[ans[i].x]-dep[ans[i].lca];
                if (ans[i].lca!=ans[i].y) as++;
                if (ans[i].x==ans[i].y) as=0;
                printf("%d\n",as);
            }
        }
        return 0;
    }


  • 相关阅读:
    hdu 5119 Happy Matt Friends
    hdu 5128 The E-pang Palace
    hdu 5131 Song Jiang's rank list
    hdu 5135 Little Zu Chongzhi's Triangles
    hdu 5137 How Many Maos Does the Guanxi Worth
    hdu 5122 K.Bro Sorting
    Human Gene Functions
    Palindrome(最长公共子序列)
    A Simple problem
    Alignment ( 最长上升(下降)子序列 )
  • 原文地址:https://www.cnblogs.com/cyendra/p/3226326.html
Copyright © 2011-2022 走看看