题目描述
小A这次来到一个景区去旅游,景区里面有N个景点,景点之间有N-1条路径。小A从当前的一个景点移动到下一个景点需要消耗一点的体力值。但是景区里面有两个景点比较特殊,它们之间是可以直接坐观光缆车通过,不需要消耗体力值。而小A不想走太多的路,所以他希望你能够告诉它,从当前的位置出发到他想要去的那个地方,他最少要消耗的体力值是多少。
输入描述:
第一行一个整数N代表景区的个数。
接下来N-1行每行两个整数u,v代表从位置u到v之间有一条路径可以互相到达。
接下来的一行两个整数U,V表示这两个城市之间可以直接坐缆车到达。
接下来一行一个整数Q,表示有Q次询问。
接下来的Q行每行两个整数x,y,代表小A的位置在x,而他想要去的地方是y。
输出描述:
对于每个询问下x,y输出一个结果,代表x到y消耗的最少体力对于每个询问下x,y输出一个结果,代表x到y消耗的最少体力对于每个询问下x,y输出一个结果,代表x到y消耗的最少体力
题解
LCA
由题目中的数据我们可以看出这个图是一棵树,两点之间的最短路径是唯一的,很自然的想到x和y点的距离就是dep[x]+dep[y]-2*dep[lca(x,y)]
题目中又有一个u和v之间不用消耗体力的条件,那每次询问就是在x->y,x->u->v->y,x->v->u->y三个距离之间找一个最小的就可以了
代码
#include<iostream> #include<algorithm> #include<map> #include<vector> #include<set> #include<string> #include<cstring> #include<cstdio> #include<cmath> #include<queue> #include<stack> using namespace std; #define ll long long #define ull unsigned long long #define pb push_back #define pii pair<int,int> #define all(A) A.begin(), A.end() #define fi first #define se second #define MP make_pair #define rep(i,n) for(register int i=0;i<(n);++i) #define repi(i,a,b) for(register int i=int(a);i<=(b);++i) #define repr(i,b,a) for(register int i=int(b);i>=(a);--i) template<typename T> inline T read(){ T s=0,f=1; char ch = getchar(); while(!isdigit(ch)) {if(ch == '-') f=-1;ch = getchar();} while(isdigit(ch)) {s=(s<<3)+(s<<1)+ch-48;ch = getchar();} return s*f; } #define gn() read<int>() #define gl() read<ll>() template<typename T> inline void print(T x) { if(x<0) putchar('-'), x=-x; if(x>9) print(x/10); putchar(x%10+'0'); } //////////////////////////////////////////////////////////////////////// const int N=3e5+100; int dp[N][30],dep[N]; vector<int> v[N]; void dfs(int node,int fa){ dep[node]=dep[fa]+1; dp[node][0]=fa; for(int i=1;(1<<i)<=dep[node];++i){ dp[node][i]=dp[dp[node][i-1]][i-1]; } for(int i=0,len=v[node].size();i<len;++i){ if(v[node][i]==fa)continue; dfs(v[node][i],node); } } int lca(int x,int y){ if(dep[x]<dep[y])swap(x,y); int tem=dep[x]-dep[y]; for(int j=0;tem;++j){ if(tem&1)x=dp[x][j]; tem>>=1; } if(x==y)return x; for(int j=29;j>=0&&x!=y;--j){ if(dp[x][j]!=dp[y][j]){ x=dp[x][j]; y=dp[y][j]; } } return dp[x][0]; } int cross(int x,int y){ return dep[x]+dep[y]-2*dep[lca(x,y)]; } //////////////////////////////////////////////////////////////////////// int main(){ int n=gn(); repi(i,2,n){ int x=gn(),y=gn(); v[x].pb(y); v[y].pb(x); } dfs(1,0); int l=gn(),r=gn(); int q=gn(); while(q--){ int x=gn(),y=gn(); int ans=min(cross(x,y),min(cross(x,l)+cross(r,y),cross(x,r)+cross(l,y))); print(ans),putchar(10); } } /** * In every life we have some trouble * When you worry you make it double * Don't worry,be happy. **/