http://acm.hdu.edu.cn/showproblem.php?pid=4547
题意:就是给你一棵树,从一个节点到它的子孙节点只需要一步,到他的祖先节点则要一步一步地向上爬x步(x为它到其祖先节点之间的边数)。给你两个节点a,b,问从a到b最少经过多少步。
思路:额。。。就是裸的LCA,求出两个点的的LCA,设为C点,那就从a到c然后再到b,从a到c就是a和c之间的深度只差,从c到b则需要1步或0步(看c是否等于b)。然后就没有然后了。这里的LCA用树链剖分实现,节点的标号用map存储。
代码如下:
#pragma comment(linker,"/STACK:100000000,100000000")
#include <iostream>
#include <string.h>
#include <stdio.h>
#include <map>
#include <algorithm>
#define maxn 100010
using namespace std;
struct edge
{
int to;
int next;
}e[maxn<<1];
int box[maxn],cnt,tot;
int siz[maxn],top[maxn],son[maxn],dep[maxn],fa[maxn];
void init()
{
tot=0;
son[0]=dep[0]=0;
memset(box,-1,sizeof(box));
cnt=0;
}
void add(int from,int to)
{
e[cnt].to=to;
e[cnt].next=box[from];
box[from]=cnt++;
}
void dfs(int now,int pre)
{
siz[now]=1;
fa[now]=pre;
son[now]=0;
dep[now]=dep[pre]+1;
int t,v;
for(t=box[now];t+1;t=e[t].next)
{
v=e[t].to;
if(v!=pre)
{
dfs(v,now);
siz[now]+=siz[v];
if(siz[son[now]]<siz[v])
{
son[now]=v;
}
}
}
}
void dfs2(int now,int tp)
{
top[now]=tp;
if(son[now])
dfs2(son[now],top[now]);
int t,v;
for(t=box[now];t+1;t=e[t].next)
{
v=e[t].to;
if(v!=fa[now]&&v!=son[now])
dfs2(v,v);
}
}
int LCA(int a, int b)
{
while (1)
{
if (top[a] == top[b])
return dep[a] <= dep[b] ? a : b;
else if (dep[top[a]] >= dep[top[b]])
a = fa[top[a]];
else b = fa[top[b]];
}
}
struct node
{
char str[50];
bool operator <(const node &a)const
{
if(strcmp(str,a.str)<0)
return true;
return false;
}
};
int vis[maxn];
map <node,int> mp;
map <node,int>::iterator itor;
int main()
{
//freopen("dd.txt","r",stdin);
int ncase;
scanf("%d",&ncase);
while(ncase--)
{
int n,m,num=0,i;
scanf("%d%d",&n,&m);
init();
node t1,t2;
memset(vis,0,sizeof(vis));
mp.clear();
for(i=1;i<n;i++)
{
int a,b;
scanf("%s%s",t1.str,t2.str);
itor=mp.find(t1);
if(itor==mp.end())
{
mp.insert(make_pair(t1,++num));
a=num;
}
else
a=itor->second;
itor=mp.find(t2);
if(itor==mp.end())
{
mp.insert(make_pair(t2,++num));
b=num;
}
else
{
b=itor->second;
}
vis[a]=1;
add(b,a);
add(a,b);
}
int root=0;
for(i=1;i<=n;i++)
{
if(!vis[i])
break;
}
root=i;
dfs(root,0);
dfs2(root,root);
while(m--)
{
int a,b;
scanf("%s%s",t1.str,t2.str);
if(n==1)
{
printf("0\n");
continue;
}
itor=mp.find(t1);
a=itor->second;
itor=mp.find(t2);
b=itor->second;
int c=LCA(a,b);
printf("%d\n",dep[a]-dep[c]+(c==b?0:1));
}
}
return 0;
}