【每日一题】8月3日题目精讲—小A的最短路
小A的最短路
https://ac.nowcoder.com/acm/problem/23482
思路:
如果没有缆车的话,就是一个利用LCA求树上任意两点距离的板子题。(有了缆车,其实还是板子题……)
有了一个缆车之后,无非就算考虑一下要不要坐缆车以及怎样坐缆车,所以:不坐缆车xy的距离就是原来的距离dist(x,y),坐缆车的话要考虑是x到u点坐缆车,还是到v点坐缆车,即dist(x,u) + dist(v,y) 和ist(x,v) + dist(u,y)
有了一个缆车之后,无非就算考虑一下要不要坐缆车以及怎样坐缆车,所以:不坐缆车xy的距离就是原来的距离dist(x,y),坐缆车的话要考虑是x到u点坐缆车,还是到v点坐缆车,即dist(x,u) + dist(v,y) 和ist(x,v) + dist(u,y)
#include<bits/stdc++.h> const int MAX=3e5+50; using namespace std; template <class T> void read(T &x) { char c; bool op = 0; while(c = getchar(), c < '0' || c > '9') if(c == '-') op = 1; x = c - '0'; while(c = getchar(), c >= '0' && c <= '9') x = x * 10 + c - '0'; if(op) x = -x; } template <class T> void write(T x) { if(x < 0) x = -x, putchar('-'); if(x >= 10) write(x / 10); putchar('0' + x % 10); } struct node { int ch,dis; }; vector<node> G[MAX*2]; int rdis[MAX]; int father[22][MAX],dep[MAX]; void dfs(int u,int f,int dis) { father[0][u]=f; rdis[u]=dis; dep[u]=dep[f]+1; for(int i=1;i<=21;i++) { father[i][u]=father[i-1][father[i-1][u]]; } int len=G[u].size(); for(int i=0;i<len;i++) { int v=G[u][i].ch; if(v==f)continue; father[0][v]=u; dfs(v,u,dis+G[u][i].dis); } } void init(int n) { memset(father,0,sizeof(father)); dep[0]=0; dfs(1,0,0); } int lca(int u,int v) { if(dep[u]>dep[v]){ swap(u,v); } for(int k=0;k<=21;k++) { if((dep[v]-dep[u])>>k&1){ v=father[k][v]; } } if(u==v)return u; for(int k=21;k>=0;k--){ if(father[k][u]!=father[k][v]){ u=father[k][u]; v=father[k][v]; } } return father[0][u]; } int distant(int u,int v) { return rdis[u]+rdis[v]-rdis[lca(u,v)]*2; } int main(){ int n; read(n); for(int i=1;i<=n-1;i++){ int a,b; read(a);read(b); G[a].push_back({b,1}); G[b].push_back({a,1}); } init(n); int x,y; read(x);read(y); int k; read(k); for(int i=1;i<=k;i++){ int c,d; read(c);read(d); int ans=min(distant(c,x)+distant(d,y),distant(c,y)+distant(d,x)); ans=min(distant(c,d),ans); printf("%d\n",ans); } return 0; }其实就是个板子题,只要有板子就行,可惜原来我没有这个板子,但是可是现在有了。