• HDU


    题目传送门:HDU - 4547 CD操作

    题目大意:

    分析:

    求出目录A 到 B所需要的CD操作次数,这里的A B 位字符串 所以用到map映射,之后直接求LCA分情况讨论即可:设求A到B的CD操作数

    1、A==B  需要的CD操作数是0

    2、A是B的最近公共祖先,则A-->B的CD操作数是0

    3、B是A的最近公共祖先,则B-->A的CD操作数是 deep[B]-deep[B]

    4、若互相不是最近公共祖先,则CD操作数是 deep[A]-deep[lca(A,B)]+1

    #include<iostream>
    #include<cstring>
    #include<map>
    #include<cstdio>
    using namespace std;
    const int MAX=100009;
    const int M=20;
    int head[MAX],cnt=0;
    int t,n,m;
    int up[MAX][M];
    int dis[MAX];
    int deep[MAX];
    char a[50],b[50];
    map<string,int>mp;
    struct Edge{
        int next,to,val;
    }edge[MAX];
    inline void add(int u,int v)
    {
        edge[cnt].to=v;
        edge[cnt].val=1;
        edge[cnt].next=head[u];
        head[u]=cnt++;
    }
    void dfs(int u)                                    //dfs遍历求出深度
    {
        for(int i=head[u];i!=-1;i=edge[i].next)
        {
            int to=edge[i].to;
            if(to==up[u][0])continue;
            deep[to]=deep[u]+1;
            up[to][0]=u;
            dfs(to);
        }
    }
    void init()                                         
    {
        for(int j=1;(1<<j)<=n;j++)
            for(int i=1;i<=n;i++)
                up[i][j]=up[up[i][j-1]][j-1];
    }
    int lca(int a,int b)
    {
        if(deep[a]<deep[b])swap(a,b);
        int d=deep[a]-deep[b];
        for(int i=0;i<M;i++)
            if((1<<i)&d)
                a=up[a][i];
                
        if(a==b)return a;
        for(int i=M-1;i>=0;i--)
        {
            if(up[a][i]!=up[b][i])
            {
                a=up[a][i];b=up[b][i];
            }
        }
        return up[a][0];
    }
    int main()
    {
        scanf("%d",&t);
        while(t--)
        {
            memset(head,-1,sizeof(head));cnt=0;
            memset(up,0,sizeof(up));
            memset(deep,0,sizeof(deep)); 
            mp.clear();
            scanf("%d %d",&n,&m);
            int count=1;
            for(int i=0;i<n-1;i++)
            {
                scanf("%s %s",a,b);                                //map将目录名映射为数字 
                if(mp[a]==0)
                    mp[a]=count++;
                if(mp[b]==0)
                    mp[b]=count++;
                add(mp[b],mp[a]);
                up[mp[a]][0]=mp[b];
            }
            for(int i=1;i<=n;i++)
            {
                if(up[i][0]==0)
                {
                    dfs(i);
                    break;
                }
            }
            init();
            int res;
            for(int i=0;i<m;i++)
            {
                scanf("%s %s",a,b);
                if(mp[a]==mp[b])res=0;                                //讨论 
                else if(lca(mp[a],mp[b])==mp[a])
                    res=1;
                else if(lca(mp[a],mp[b])==mp[b])
                    res=deep[mp[a]]-deep[lca(mp[a],mp[b])];
                else 
                    res=deep[mp[a]]-deep[lca(mp[a],mp[b])]+1;
                printf("%d
    ",res);
            }
        }
        return 0;
    }
  • 相关阅读:
    常见的兼容问题
    清除浮动
    简单的容器盒子
    查找并替换中文字符
    遍历对象属性值
    统一服务器和界面的传输格式
    随机生成包含大小写和数字的字符串
    网站翻译功能
    菜鸟安装vue-devtool 工具
    安装虚拟机所遇到的问题
  • 原文地址:https://www.cnblogs.com/LjwCarrot/p/9690181.html
Copyright © 2020-2023  润新知