宁波多校(四) D题 树上的点到链(lca)
先求一下lca,之后比较一下给定两点的lca与所求点的关系后分类讨论
#include<bits/stdc++.h> using namespace std; typedef long long ll; const int N=2e5+10; int h[N],ne[N],e[N],idx; int n,q; int depth[N],fa[N][25]; void add(int a,int b){ e[idx]=b,ne[idx]=h[a],h[a]=idx++; } void bfs(){ memset(depth,0x3f,sizeof depth); depth[0]=0,depth[1]=1; int i; queue<int> q; q.push(1); while(q.size()){ int t=q.front(); q.pop(); for(i=h[t];i!=-1;i=ne[i]){ int j=e[i]; if(depth[j]>depth[t]+1){ depth[j]=depth[t]+1; q.push(j); fa[j][0]=t; for(int k=1;k<=21;k++){ fa[j][k]=fa[fa[j][k-1]][k-1]; } } } } } int lca(int a,int b){ if(depth[a]<depth[b]) swap(a,b); int i; for(i=21;i>=0;i--){ if(depth[fa[a][i]]>=depth[b]){ a=fa[a][i]; } } if(a==b) return a; for(i=21;i>=0;i--){ if(fa[a][i]!=fa[b][i]){ a=fa[a][i]; b=fa[b][i]; } } return fa[a][0]; } int main(){ ios::sync_with_stdio(false); int n,m; cin>>n>>m; int i; memset(h,-1,sizeof h); for(i=1;i<n;i++){ int u,v; cin>>u>>v; add(u,v); add(v,u); } bfs(); // cout<<"ss"<<endl; while(m--){ int x,y,c; cin>>x>>y>>c; int p=lca(x,y); if(depth[y]>depth[x]) swap(x,y); int g=lca(p,c); if(g!=p){ cout<<depth[p]+depth[c]-2*depth[g]<<endl; } else{ if(lca(c,x)==c||lca(c,y)==c){ cout<<0<<endl; } else{ if(lca(c,x)==x){ cout<<depth[c]-depth[x]<<endl; } else if(lca(c,y)==y) cout<<min(depth[c]-depth[y],depth[c]-depth[lca(c,x)])<<endl; else{ int kk=lca(x,c); int dd=lca(c,y); cout<<min(depth[c]-depth[kk],depth[c]-depth[dd])<<endl; } } } } }
没有人不辛苦,只有人不喊疼