HDU - 4547 CD操作 (LCA倍增)

Posted ljwcarrot

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HDU - 4547 CD操作 (LCA倍增)相关的知识,希望对你有一定的参考价值。

题目传送门: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;
}

 

以上是关于HDU - 4547 CD操作 (LCA倍增)的主要内容,如果未能解决你的问题,请参考以下文章

hdu2856(倍增lca模版题)

洛谷P3379lca,HDU2586,洛谷P1967货车运输,倍增lca,树上倍增

hdu2586 lca倍增法

hdu 2586 How far away ? 倍增求LCA

HDU - 6115 Factory (LCA 倍增)

HDU 2887 Watering Hole(MST + 倍增LCA)