Problem Description
在Windows下我们可以通过cmd运行DOS的部分功能,其中CD是一条很有意思的命令,通过CD操作,我们可以改变当前目录。
这里我们简化一下问题,假设只有一个根目录,CD操作也只有两种方式:
1. CD 当前目录名\...\目标目录名 (中间可以包含若干目录,保证目标目录通过绝对路径可达)
2. 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操作。
数据保证合法,一定存在一个根目录,每个目录都能从根目录访问到。
每个样例首先一行是两个整数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
类别:图论 难度:1.5
题意分析:给定一个树即每个点的父节点,求从a到b需要几步(向上遍历一次算一步,向下遍历到子树任一节点算一步)。
先用map存储<字符串,标号>,然后记录每个点父节点,再计算每个点的深度,之后对于给定的所求a点和b点,求a和b遍历到最近的共同父节点的距离,记为dx,dy,最后结果即为dx+((dy>0)?1:0)。一开始map忘记每次循环clear,导致runtime error(堆栈溢出)
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<map>
#include<string>
using namespace std;
const int N=101010;
map<string,int> in;
int n,m,dep[N],pa[N],qu[N];
char a[200],b[200];
int main()
{
int t;
scanf("%d",&t);
for(int cnt=1;cnt<=t;cnt++)
{
memset(dep,-1,sizeof(dep));
memset(pa,0,sizeof(pa));
in.clear();
scanf("%d%d",&n,&m);
int i,j,ct=1;
for(i=0;i<n-1;i++)
{
scanf("%s%s",a,b);
map<string,int>::iterator it;
it = in.find(a);
if(it==in.end()) in[a]=ct++;
it = in.find(b);
if(it==in.end()) in[b]=ct++;
pa[in[a]]=in[b];
}
int top,tmp,kn;
for(i=1;i<=n;i++)
if(pa[i]==0) {dep[i]=0;break;}
for(i=1;i<=n;i++)
{
if(pa[i]==0) continue;
top=0;
tmp=pa[i];
while(dep[tmp]<0)
{
qu[top++]=tmp;
tmp=pa[tmp];
}
kn=dep[tmp];
while(top>0)
{
dep[qu[--top]]=++kn;
}
dep[i]=++kn;
}
for(i=0;i<m;i++)
{
scanf("%s%s",a,b);
int x=in[a],y=in[b];
int dx=0,dy=0;
while(pa[x]>0&&dep[x]>dep[y])
{
x=pa[x];
dx++;
}
while(pa[y]>0&&dep[y]>dep[x])
{
y=pa[y];
dy++;
}
while(x!=y)
{
x=pa[x];y=pa[y];
dx++;dy++;
}
printf("%d\n",dx+((dy>0)?1:0));
}
}
}