首先,题目有个条件:n个节点,n-1条路径,所以,这是一棵树。之后,会再在u,v之间加入一条边权为0的边,让我们求图上任意两点的最短路。
若我们忽略新加入的uv边,那直接求lca求距离就行了。但是,现在加入了uv边,但是,我们可以想到,如果真正的最短路径不经过uv边,那么答案依旧还是lca求得的结果,因此,我们可以分两种情况:经过uv边和不经过uv边。
不经过uv边上面已经说过了,若经过uv边,肯定经过u,v中的某一个节点,则,我们可以把这个节点(u和v任选一个)作为中转节点(这里假设选了u),那么,很显然,在经过u的情况下的最短路径对dis[x]+disy,因此,我们可以以u点为原点跑一次单源点最短路,以此求得在经过u点情况下的最短路径。
之后,让通过树上距离求得的距离和最短路跑出来的距离取个min就可以了。
类似题目:https://ac.nowcoder.com/acm/problem/19814,都是先处理树上距离,再处理另外边,只是处理方式不一样。
AC代码
#include <iostream>
#include <map>
#include <ctime>
#include <vector>
#include <climits>
#include <algorithm>
#include <random>
#include <cstring>
#include <cstdio>
#include <map>
#include <set>
#include <bitset>
#include <queue>
#define inf 0x3f3f3f3f
#define IOS ios_base::sync_with_stdio(0); cin.tie(0);
#define rep(i, a, n) for(register int i = a; i <= n; ++ i)
#define per(i, a, n) for(register int i = n; i >= a; -- i)
#define ONLINE_JUDGE
using namespace std;
typedef long long ll;
const int mod=1e9+7;
template<typename T>void write(T x)
{
if(x<0)
{
putchar('-');
x=-x;
}
if(x>9)
{
write(x/10);
}
putchar(x%10+'0');
}
template<typename T> void read(T &x)
{
x = 0;char ch = getchar();ll f = 1;
while(!isdigit(ch)){if(ch == '-')f*=-1;ch=getchar();}
while(isdigit(ch)){x = x*10+ch-48;ch=getchar();}x*=f;
}
int gcd(int a,int b){return b==0?a:gcd(b,a%b);}
int lcm(int a,int b){return a/gcd(a,b)*b;};
ll ksm(ll a,ll n){//看是否要mod
ll ans=1;
while(n){
if(n&1) ans=((ans%mod)*(a%mod))%mod;
a=((a%mod)*(a%mod))%mod;
n>>=1;
}
return ans%mod;
}
//==============================================================
#define int ll
const int maxn=3e5+10;
struct Edge{
int to,next,w;
}e[maxn<<1];
int n;
int cnt,head[maxn];
void add(int x,int y,int w){
e[cnt].to=y;
e[cnt].next=head[x];
e[cnt].w=w;
head[x]=cnt++;
}
int par[maxn][20],lg[maxn],depth[maxn];
void dfs(int u,int fa,int de){
par[u][0]=fa;
depth[u]=de;
rep(i,1,lg[de]-1){
par[u][i]=par[par[u][i-1]][i-1];
}
for(int i=head[u];~i;i=e[i].next){
int v=e[i].to;
if(v==fa) continue;
dfs(v,u,de+1);
}
}
int lca(int a,int b){
if(depth[a]<depth[b]) swap(a,b);
while(depth[a]>depth[b]) a=par[a][lg[depth[a]-depth[b]]-1];
if(a==b) return a;
for(int i=lg[depth[a]]-1;i>=0;i--){
if(par[a][i]!=par[b][i]){
a=par[a][i];
b=par[b][i];
}
}
return par[a][0];
}
int dis[maxn],vis[maxn];
struct node{
int u,dis;
node(int _u,int _d){
u=_u;
dis=_d;
}
};
auto cmp=[](node&a,node&b){
return a.dis>b.dis;
};
priority_queue<node,vector<node>,decltype(cmp)> que(cmp);
void dij(int s){
memset(dis,inf,sizeof(dis));
que.push(node(s,0));
dis[s]=0;
while(!que.empty()){
node a=que.top();que.pop();
int u=a.u;
if(vis[u]) continue;
vis[u]=1;
for(int i=head[u];~i;i=e[i].next){
int v=e[i].to;
if(dis[v]>dis[u]+e[i].w){
dis[v]=dis[u]+e[i].w;
que.push(node(v,dis[v]));
}
}
}
}
signed main()
{
#ifndef ONLINE_JUDGE
freopen("in.txt","r",stdin);
freopen("out.txt","w",stdout);
#endif
//===========================================================
rep(i,1,maxn-1) lg[i]=lg[i-1]+((1<<lg[i-1])==i);
memset(head,-1,sizeof(head));
read(n);
rep(i,2,n){
int a,b;read(a),read(b);
add(a,b,1),add(b,a,1);
}
dfs(1,-1,0);
int u,v;read(u),read(v);
add(u,v,0);add(v,u,0);
dij(u);
int q;read(q);
//rep(i,1,n) cerr<<dis[i]<<" ";
//cerr<<endl;
while(q--){
int x,y;read(x),read(y);
int res1=depth[x]+depth[y]-2*depth[lca(x,y)];
int res2=dis[x]+dis[y];
write(min(res1,res2)),putchar('\n');
}
//===========================================================
return 0;
}
京公网安备 11010502036488号