Hdu 4547 CD操作 LCA问题

来源:互联网 发布:荣威rx5矩阵大灯 编辑:程序博客网 时间:2024/05/16 12:30

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
23 1B AC AB C3 2B AC BA CC A
 

Sample Output
212
 

Source
2013金山西山居创意游戏程序挑战赛——初赛(1)
 

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