CD操作
Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 65535/32768 K (Java/Others)Total Submission(s): 2637 Accepted Submission(s): 724
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思路:要求u到v,把u、v的lca求出来,设为t,那么肯定是先u到t再到v,u到t的步数刚好是他们的深度差,一个数组存深度差就可以了。t和v如果不相等就是一步,相等就是0步 代码:#include <iostream> #include <stdio.h> #include <string.h> #include <algorithm> #include <queue> #include <stack> #include <map> using namespace std; const int inf=0x3f3f3f3f; const int M=100010; const int N=100010; int head[N],h[N],dis[N],f[N],a[N]; bool in[N],vis[N]; int cnt,num,tt; string s1,s2; int n,m; map<string,int>mp; struct node { int u,v,w,next; }e[M<<1],q[M<<1]; void addedge(int u,int v,int w) { e[num].v=v; e[num].w=w; e[num].next=head[u]; head[u]=num++; } void addque(int u,int v,int w) { q[tt].v=v; q[tt].w=w; q[tt].next=h[u]; h[u]=tt++; q[tt].v=u; q[tt].w=w; q[tt].next=h[v]; h[v]=tt++; } void init() { cnt=num=tt=0; mp.clear(); memset(f,-1,sizeof(f)); memset(head,-1,sizeof(head)); memset(h,-1,sizeof(h)); memset(in,false,sizeof(in)); memset(vis,false,sizeof(vis)); memset(dis,0,sizeof(dis)); } int findx(int x) { return f[x]==-1 ?x:f[x]=findx(f[x]); } void unio(int x,int y) { int xx=findx(x); int yy=findx(y); if(xx!=yy)f[yy]=xx; } void tarjan(int u) { int i; for(i=head[u];i!=-1;i=e[i].next) { int v=e[i].v; if(vis[v])continue; dis[v]=dis[u]+e[i].w; tarjan(v); unio(u,v); } vis[u]=true; for(i=h[u];i!=-1;i=q[i].next) { int v=q[i].v; if(vis[v]) { if(~i&1) { a[q[i].w]=dis[u]-dis[findx(v)]+(findx(v)==v ?0:1); } else a[q[i].w]=dis[v]-dis[findx(v)]+(findx(v)==u ?0:1); } } } int main() { int T; scanf("%d",&T); while(T--) { init(); scanf("%d%d",&n,&m); int i,j; for(i=0;i<n-1;i++) { cin>>s1>>s2; if(!mp[s1])mp[s1]=++cnt; if(!mp[s2])mp[s2]=++cnt; addedge(mp[s2],mp[s1],1); in[mp[s1]]=true; } for(i=0;i<m;i++) { cin>>s1>>s2; if(!mp[s1])mp[s1]=++cnt; if(!mp[s2])mp[s2]=++cnt; addque(mp[s1],mp[s2],i); } for(i=1;i<=cnt;i++) { if(!in[i]) { tarjan(i); break; } } for(i=0;i<m;i++) { printf("%d\n",a[i]); } } return 0; }