A 小A的最短路 LCA用欧拉序列转化为 RMQ 问题 求树上两点距离
分析
x y 两点的距离,可以看作它们到根节点的距离 - 2 * 它们的最近公共祖先到根节点的距离
t1 ,t2 之间不需要时间,所以题目要求的是 x-y ,t1-x+t2-y,t1-y+t2-x三条链,哪条链最短
求欧拉序,将深度看作到根节点的距离,用st数组找出它们的根节点,再套用 下面的公式 就可以了
dep[a] + dep[b] - 2 * dep[t];
//-------------------------代码---------------------------- //#define int ll const int N = 3e5+10,M = N * 2; int n,m; int e[M],ne[M],w[M],h[N],idx; // int cnt,first[N],b[M]; void add(int a,int b,int c) { e[idx] = b,ne[idx] = h[a],w[idx] = c,h[a] = idx ++ ; } int dep[N],first[N],step; int a[M]; void dfs(int u,int fa) { first[u] = ++ step; a[step] = u; for(int i = h[u];~i;i=ne[i]) { int son = e[i]; if(son == fa) continue; dep[son] = dep[u] + w[i]; dfs(son,u); a[++step] = u; // db(step); } } int f[M][30]; void init() { int m = (int)(log(1.0*step) / log(2.0)); for(int j = 0;j<=m;j++) { for(int i = 1;i + (1<<j) - 1<= step;i ++ ) { if(!j) f[i][j] = a[i]; else { f[i][j] = dep[f[i][j-1]] < dep[f[i+(1<<j-1)][j-1]] ? f[i][j-1]: f[i+(1<<j-1)][j-1]; } } } } int st_find(int l,int r) { int len=(int) (log(1.0*(r-l+1))/log(2.0)); return dep[f[l][len]] < dep[f[r - (1 << len) + 1][len]] ? f[l][len] : f[r - (1 << len) + 1][len]; } int lca(int u,int v) { if(first[u] > first[v]) swap(u,v); return st_find(first[u],first[v]); } int dist(int a,int b) { int t = lca(a,b); return dep[a] + dep[b] - 2 * dep[t]; } void solve() { // cin>>n>>m; cin>>n; ms(h,-1); fo(i,1,n-1) { int u,v;cin>>u>>v; if(i != n)add(u,v,1); else add(u,v,0); } int t1,t2; cin>>t1>>t2; // db(step); dfs(1,-1); init(); // dbb(step,n*2); int q;cin>>q; while(q -- ) { int x,y;cin>>x>>y; printf("%d\n",min(min(dist(x,t1)+dist(t2,y),dist(x,t2)+dist(t1,y)),dist(x,y))); } } signed main(){ AC(); clapping();TLE; // while(cin>>n,n) // while(cin>>n>>m,n,m) // int t;cin>>t;while(t -- ) solve(); // {solve(); } return 0; } /*样例区 */ //------------------------------------------------------------