小A的最短路
https://ac.nowcoder.com/acm/problem/23482
题意:给你一颗树,问你dis(x,y),其中有个特殊通道dx----->dy的dis=0,Q次询问问你dis(u,v);
思路:首先没有这个限制条件我们直接求dis(u,v)就行,有了这个条件我们需要考虑是否走dx--->dy;那么会新增几条路,u->dx->dy->v或者u->dy->dx->v;直接算一下取最小值即可。
#include<bits/stdc++.h> using namespace std; typedef long long ll; const ll INF=1e15+7; const int N=4e5+5; const int M=1e6+5; int f[N][30],d[N]; struct node { int to,w; }; vector<node>G[N]; int n,m,dep; void bfs() { queue<node>q; q.push({1,1}); d[1]=1; dep=(int)(log(n)/log(2))+1; while(!q.empty()) { int u=q.front().to; q.pop(); int len=G[u].size(); for(int i=0; i<len; i++) { int v=G[u][i].to,w=G[u][i].w; if(d[v]) continue; d[v]=d[u]+w; f[v][0]=u; for(int j=1; j<=20; j++) f[v][j]=f[f[v][j-1]][j-1]; q.push({v,d[v]}); } } } int LCA(int x,int y) { if(d[x]<d[y]) swap(x,y); for(int i=20; i>=0; i--) { if(d[f[x][i]]>=d[y]) x=f[x][i]; } if(x==y) return x; for(int i=20; i>=0; i--) { if(f[x][i]!=f[y][i]) x=f[x][i],y=f[y][i]; } return f[x][0]; } int dx,dy; int dist(int x,int y) { int fa=LCA(x,y); return d[x]+d[y]-2*d[fa]; } int main() { cin>>n; for(int j=1; j<n; j++) { int u,v,w; scanf("%d%d",&u,&v); G[u].push_back({v,1}); G[v].push_back({u,1}); } bfs(); cin>>dx>>dy; cin>>m; while(m--) { int x,y; scanf("%d%d",&x,&y); int dis=dist(x,y); dis=min(dist(x,dy)+dist(y,dx),dis); dis=min(dist(x,dx)+dist(y,dy),dis); printf("%d\n",dis); } }