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
#include
#include
#include
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<)
        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)
        if((1<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;i1;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)
        {
            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\n",res);
        }
    }
    return 0;
}

 

你可能感兴趣的:(HDU - 4547 CD操作 (LCA倍增))