学习链接http://www.cnblogs.com/JVxie/p/4854719.html
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
using namespace std;
#define maxn 100010
typedef long long ll;
vector<int>s[maxn],q[maxn];
vector<ll>w[maxn];
int n,m,fa[maxn],k[100][100],a[maxn],b[maxn];
bool vis[maxn];
inline int read(){
int num=0,f=1; char c=getchar();;
while(!isdigit(c)){if(c=='-') f=-1; c=getchar();}
while(isdigit(c)){num=(num<<1)+(num<<3)+(c^48); c=getchar();}
return num*f;
}
int find(int x){
if(fa[x]!=x) fa[x]=find(fa[x]);
return fa[x];
}
inline int un(int a,int b){
int A=find(a),B=find(b);
fa[A]=B;
}
void lca(int x){
vis[x]=1;
int num=s[x].size();
for(int i=0;i<num;i++){
int u=s[x][i];
if(!vis[u]){
lca(u);
un(u,x);//和并查集不一样这里必须有顺序
}
}
num=q[x].size();
for(int i=0;i<num;i++){
int e=q[x][i];
if(vis[e]){
k[x][e]=find(e);
k[e][x]=k[x][e];//注意双向更新
}
}
}
inline int in(){
n=read(); m=read();
for(int i=1;i<=n;i++) fa[i]=i;
for(int i=1;i<n;i++){
ll u,v,w;
u=read(); v=read();
s[u].push_back(v);
s[v].push_back(u);
}
for(int i=1;i<=m;i++){
a[i]=read(); b[i]=read();
q[a[i]].push_back(b[i]);
q[b[i]].push_back(a[i]);
}
lca(1);
}
inline int out(){
for(int i=1;i<=m;i++) cout<<k[a[i]][b[i]]<<endl;
}
int main(){
in();
out();
}
//9 2
//1 2
//1 3
//2 4
//2 5
//5 7
//5 8
//7 9
//3 6
//2 3
//7 8