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;
    }


  • 相关阅读:
    javascript 利用
    javascript 事件委托(代理)
    【风马一族_日常灵感】 弯曲的几何学 曲角
    【风马一族_Python】 安装pip与Numpy
    【风马一族_Python】 更替pip的版本
    【风马一族_Android】Android学习
    气味分享系统
    【风马一族_构思】寻找二点间的最短距离
    【风马一族_Java】使用java,画出任意大小的菱形
    【风马一族_Java】9*9口诀
  • 原文地址:https://www.cnblogs.com/cyendra/p/3226326.html
Copyright © 2011-2022 走看看