题意:告诉你CD操作的具体方法,然后给出当前目录和目标目录,问要多少步才能从当前目录到目标目录。
解法:最近公共祖先模板题,但是要注意几种特殊情况,例如,当前目录是A,目标目录是B,而A是B的祖先,那么这样可以一步到达,另外,当只有一个节点的时候也会有询问,比如A A,那么这个时候是0,处理好这些,问题就解决了。。。
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<queue>
#include<set>
#include<stack>
#include<vector>
#include<algorithm>
#include<iostream>
#include<map>
#include<math.h>
using namespace std;
//LCA灵魂是当搜索完一层的时候 才标记次节点为父亲
#define MAXN 100001
map<string,int> mp;
int father[MAXN];
int n,m;
int in[MAXN];
bool flag[MAXN];
int root;
typedef struct Q
{
int to,next;
}Q;
Q edge[MAXN*2];
int ans[MAXN];
int dp[MAXN];
int cnt,box[MAXN];
typedef struct F
{
int from,to;
}F;
F sum[MAXN];
void Make_E(int from,int to)
{
edge[++cnt].to=to;
edge[cnt].next=box[from];
box[from]=cnt;
}
typedef struct F1
{
int to,next,index;
}F1;
F1 Edge[MAXN*2];
int cnt1,Box[MAXN];
void Make_E1(int from,int to,int C)
{
Edge[++cnt1].to=to;
Edge[cnt1].index=C;
Edge[cnt1].next=Box[from];
Box[from]=cnt1;
}
void Init()
{
int i,j,k;
char a[44],b[44];
mp.clear();
int count=0;
cnt=0;
cnt1=0;
scanf("%d%d",&n,&m);
for(i=1;i<=n;i++)
{
box[i]=-1;
in[i]=0;
Box[i]=-1;
}
for(i=1;i<n;i++)
{
father[i]=i;
scanf("%s %s",a,b);
int A,B;
if(!mp[a])
{
mp[a]=++count;
}
if(!mp[b])
{
mp[b]=++count;
}
A=mp[a];
B=mp[b];
Make_E(B,A);
in[A]++;
}
father[n]=n;
for(i=1;i<=m;i++)
{
ans[i]=0;
scanf("%s %s",a,b);
int A=mp[a];
int B=mp[b];
sum[i].from=A;
sum[i].to=B;
Make_E1(A,B,i);
Make_E1(B,A,i);
}
root=0;
for(i=1;i<=n;i++)
{
if(in[i])
continue;
root=i;
}
return ;
}
//非路径压缩
int find(int x)
{
int r=x;
while(r!=father[r])
r=father[r];
return r;
}
void bfs(int x)
{
int i,j,k;
flag[x]=1;
for(i=Box[x];i+1;i=Edge[i].next)
{
int y=Edge[i].to;
int index=Edge[i].index;
if(flag[y])
{
if(x==y)
{
ans[index]=0;
continue;
}
int Y=find(y);
if(sum[index].from==x&&sum[index].to==y)
{
if(x==Y)
{
ans[index]=1;
}
else if(y==Y)
{
ans[index]=dp[x]-dp[Y];
}
else
{
ans[index]=1+dp[x]-dp[Y];
}
}
else
{
if(y==Y)
{
ans[index]=1;
}
else if(Y==x)
{
ans[index]=dp[y]-dp[Y];
}
else
{
ans[index]=1+dp[y]-dp[Y];
}
}
}
}
for(i=box[x];i+1;i=edge[i].next)
{
int to=edge[i].to;
if(!flag[to])
{
dp[to]=dp[x]+1;
bfs(to);
father[to]=x;
}
}
return ;
}
// LCA
void Slove()
{
int i,j,k;
dp[root]=0;
memset(flag,0,sizeof(flag));
bfs(root);
for(i=1;i<=m;i++)
printf("%d\n",ans[i]);
}
int main()
{
int i,j,k;
int t;
scanf("%d",&t);
while(t--)
{
Init();
Slove();
}
return 0;
}