思路: 这里可以分析出来,如果是从父节点跳到子节点,那么直接1步到位,如果不是,那么就先算跳到lca(a,b)的距离,如果lca是目标点,这就是结果,如果不是,还要+1。
注意特殊情况,坑死人。我用的map,如果上hash估计会更快一点。
#include <algorithm>
#include <cstdio>
#include <iostream>
#include <cstring>
#include <map>
using namespace std;
int t,n,m;int num = 1;
map<string ,int> id;
const int maxn = 1e5+10;
struct node
{
int to,w,next,f;
node(){}
node(int a,int b,int c){to = a; w = b; next = c;}
}edge[maxn << 1], qu[maxn << 1];
int h[maxn], hq[maxn], f[maxn], dis[maxn] ,vis[maxn], col[maxn] ,ans[maxn], isRoot[maxn];
int edgenum = 0, qnum = 0;
void init()
{
id.clear();
for(int i = 1; i <= maxn; i++)
h[i] = hq[i] = -1, f[i] = i, dis[i] = col[i] = isRoot[i] = 0;
edgenum = qnum = 0;
num = 1;
}
void add(int f,int t,int w)
{
edge[edgenum] = node(t , w , h[f]);
h[f] = edgenum++;
}
void addq(int f,int t,int id,int flag)
{
qu[qnum] = node(t , id , hq[f]);
qu[qnum].f = flag;
hq[f] = qnum++;
}
int getf(int i)
{ return i == f[i] ? i : f[i] = getf(f[i]); }
void join(int a,int b)
{
int i = getf(a), j = getf(b);
if(i != j)
f[j] = i;
}
void tarjan(int u)
{
for(int i = h[u] ; ~i; i = edge[i].next)
{
int v = edge[i].to;
if(!vis[v])
{
vis[v] = 1;
dis[v] = dis[u] + edge[i].w;
tarjan(v);
f[v] = u;
f[getf(u)] = u;
vis[v] = 0;
}
}
col[u] = 1;
for(int i = hq[u]; ~i; i = qu[i].next)
{
int v = qu[i].to, id = qu[i].w , flag = qu[i].f;
if(!col[v]) continue;
if(u == v) { ans[id] = 0; continue;}
if(getf(v) == u)
{
if(flag) ans[id] = dis[v] - dis[u];
else ans[id] = 1;
}
else
{
if(flag) ans[id] = dis[v] - dis[getf(v)] + 1;
else ans[id] = dis[u] - dis[getf(v)] + 1;
}
}
}
int main()
{
scanf("%d",&t);
char a[50],b[50];
while(t--)
{
scanf("%d%d",&n,&m);
if(n == 1)
{
for(int i = 0; i < m ; i++)
{
scanf("%s%s",&a,&b);
printf("0\n");
}
continue;
}
init();
for(int i = 1; i <= n-1 ; i++)
{
scanf("%s%s",a,b);
if(id.count(a) == 0) id[a] = num++;
if(id.count(b) == 0) id[b] = num++;
add(id[b],id[a],1);
isRoot[id[a]] ++;
}
for(int i = 1; i <= m; i++)
{
scanf("%s%s",&a,&b);
int ia = id[a], ib = id[b];
addq(ia,ib,i,0); addq(ib,ia,i,1);
}
int r;
for(int i = 1; i < num; i++)
if(isRoot[i] == 0) {r = i;break;}
vis[r] = 1; dis[r] = 0;
tarjan(r);
vis[r] = 0;
for(int i = 1; i <= m ; i++)
printf("%d\n",ans[i]);
}
return 0;
}