【每日一题】8月3日题目精讲—小A的最短路

来源:牛客网:

时间限制:C/C++ 3秒,其他语言6秒
空间限制:C/C++ 262144K,其他语言524288K
64bit IO Format: %lld

题目描述

小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消耗的最少体力 示例1

输入
复制

4
1 2
1 3
2 4
3 4
2
1 3
3 4

输出
复制

1
0

备注:
1≤N≤3e5, 1≤Q≤1e6

题解:

如果没有缆车就是lca
但是有了缆车也不怕,我们就考虑(u,v),从u到v是否需要坐缆车。假设缆车是(x,y),u到v远距离是dis(u,v),考虑缆车后就是看u是到x坐还是到y坐
dis(u,x)+dis(y,v)或dis(u,y)+dis(x,v)
看哪个距离最近即可
(复习lca)

代码:

#include<bits/stdc++.h>
#define mp make_pair
#define se second
#define fi first
using namespace std;

typedef long long ll;
//typedef pair<int, int> pii;
//typedef pair<ll, int> pli;
//typedef pair<ll, ll> pll;
typedef long double ld;

const int N=1e6+10;
const int MAXN=20010;
const int INF=0x3f3f3f3f;
const double eps=0.0000001;
const ll mod=998244353;
int head[N],to[N],nx[N],tot=1;//n个点。n-1条边
int dep[N];
int sz[N];
int fa[N][32];
int n;
void add(int u,int v){
    to[tot]=v;
    nx[tot]=head[u];
    head[u]=tot++;
}
void dfs(int u,int f,int step){
    dep[u]=step;
    fa[u][0]=f;
    sz[u]=1;
    for(int i=1;i<=21;i++){
        fa[u][i]=fa[fa[u][i-1]][i-1];
 
    }
    for(int i=head[u];i;i=nx[i]){
        int v=to[i];
        if(f==v)continue;
        dfs(v,u,step+1);
        sz[u]+=sz[v];
    }
}
int LCA(int u,int v){
    if(dep[u]<dep[v])swap(u,v);
    int d=dep[u]-dep[v];
    for(int i=0;(1<<i)<=d;i++){
        if((1<<i)&d){
            u=fa[u][i];
        }
    }
    if(u==v)return u;
    for(int i=21;i>=0;i--){
        if(fa[v][i]!=fa[u][i]){
            v=fa[v][i];
            u=fa[u][i];
        }
    }
    return fa[u][0];
}
int main(){
    int n; scanf("%d",&n);
    memset(head,-1,sizeof(head));
    for(int i = 1; i < n; ++i){
        int u,v;scanf("%d%d",&u,&v);
        add(u,v);
        add(v,u);
    }
    dfs(1,0,1);
    int a,b;scanf("%d%d",&a,&b);
    int q; scanf("%d",&q);
    while(q--){
        int u, v;
        scanf("%d%d",&u,&v);
        int lca = LCA(u,v);
        int ans = dep[u] +dep[v] - dep[lca]*2;
        int x = LCA(u,a);
        int y = LCA(b,v);
        ans = min(ans,dep[u] +dep[a] - dep[x]*2 + dep[b] +dep[v] - dep[y]*2);
        x = LCA(u,b);
        y = LCA(v,a);
        ans = min(ans,dep[u] +dep[b] - dep[x]*2 + dep[a] +dep[v] - dep[y]*2);
        printf("%d\n",ans);
    }
    return 0;
}

posted @ 2020-08-22 22:44  回归梦想  阅读(73)  评论(0编辑  收藏  举报