首先假设我们不考虑 u 和 v 两点的缆车,那么 x 和 y 之间的路程就是 x 和 y 的深度减去他们的 lca 的深度。
接下来我们考虑使用缆车,无非也就两种情况:
- x -> u -> v -> y
- x -> v -> u -> y
我们对上面三种情况取一个 min 就行了。
加快读的话可以跑到 600 ms
#include <bits/stdc++.h>
using namespace std;
#define mem(a,b) memset(a,b,sizeof(a))
#define pii pair<int,int>
const int inf = 0x3f3f3f3f;
const int maxn = 301110;
const int M = 1e9+7;
int n,q,xx,yy;
vector<int> v[maxn];
int sz[maxn],fa[maxn],d[maxn],son[maxn];
void dfs1(int u,int pre)
{
sz[u] = 1;fa[u] = pre;d[u] = d[pre]+1;
for(auto i : v[u])
{
if(i == pre) continue;
dfs1(i,u);
sz[u] += sz[i];
if(sz[son[u]] < sz[i]) son[u] = i;
}
}
int top[maxn],idx;
void dfs2(int u,int t)
{
top[u] = t;
if(!son[u]) return;
dfs2(son[u],t);
for(auto i : v[u])
{
if(i == fa[u] || i == son[u]) continue;
dfs2(i,i);
}
}
int lca(int x,int y)
{
for(;top[x] != top[y];d[top[x]]>d[top[y]]?x=fa[top[x]]:y=fa[top[y]]);
return d[x]<d[y]?x:y; //在一条链上了
}
int dis(int x,int y)
{
return d[x]+d[y]-2*d[lca(x,y)];
}
signed main()
{
ios::sync_with_stdio(false);cin.tie(0);
cin>>n;
int x,y;
for(int i = 1; i < n; i++)
{
cin>>x>>y;
v[x].push_back(y);
v[y].push_back(x);
}
dfs1(1,1);dfs2(1,1);
cin>>xx>>yy;
cin>>q;
while(q--)
{
cin>>x>>y;
int ans = dis(x,y);
ans = min(ans,dis(x,xx)+dis(y,yy));
ans = min(ans,dis(x,yy)+dis(y,xx));
cout<<ans<<endl;
}
return 0;
} 
京公网安备 11010502036488号