小A的最短路 LCA

小A的最短路

https://ac.nowcoder.com/acm/problem/23482

题目描述:
小A这次来到一个景区去旅游,景区里面有N个景点,景点之间有N-1条路径。小A从当前的一个景点移动到下一个景点需要消耗一点的体力值。但是景区里面有两个景点比较特殊,它们之间是可以直接坐观光缆车通过,不需要消耗体力值。而小A不想走太多的路,所以他希望你能够告诉它,从当前的位置出发到他想要去的那个地方,他最少要消耗的
体力值是多少。
题解:可以理解为LCA的模板题了,因为他N个点只有N-1条边,所以是一棵树,但是这个题有一个比较特别的地方,有两个点之间是不需要花体力就可以到达的,这样的话我们就多了在模板题的基础上,也就是他在这棵树上搭了一个通道,所以只需要每次特判一下是否通过这个通道会更近即可也就是

dis(u,v)
dis(u,x)+dis(v,y)
dis(u,y)+dis(v,x)

这三者之间的最小值。

/*Keep on going Never give up*/
#pragma GCC optimize(3,"Ofast","inline")
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <stdlib.h>
#include <queue>
#include <string>
const int maxn = 1e6+10;
const int MaxN = 0x3f3f3f3f;
const int MinN = 0xc0c0c00c;
typedef long long ll;
const int mod = 1e9+7;
using namespace std;
const int maxlog=20;
struct node{
    int to,next;
}edge[maxn];

int head[maxn],cnt=1;
int deep[maxn];
int fa[maxn][maxlog+1];

inline void add(int u,int v){
    edge[cnt].to=v;
    edge[cnt].next=head[u];
    head[u]=cnt++;
}
void dfs(int root,int father){
    //cout<<root<<endl;
    fa[root][0]=father;
    deep[root]=deep[father]+1;
    for(int i=1;(1<<i)<=deep[root];i++){
        fa[root][i]=fa[fa[root][i-1]][i-1];
    }
    for(int i=head[root];i;i=edge[i].next){
        if(edge[i].to==father) continue;
        dfs(edge[i].to,root);
    }
}

int lca(int x,int y){
    if(deep[x]>deep[y]) swap(x,y);
    for(int i=maxlog;i>=0;i--){
        if(fa[y][i]!=-1&&deep[fa[y][i]]>=deep[x]){
            y=fa[y][i];
        }
    }
    if(x==y) return x;
    for(int i=maxlog;i>=0;i--){
        if(fa[x][i]!=-1&&fa[y][i]!=-1&&fa[x][i]!=fa[y][i]){
            x=fa[x][i];
            y=fa[y][i];
        }
    }
    return fa[x][0];
}
inline int dis(int u,int v){
    return deep[u]+deep[v]-2*deep[lca(u,v)];
}
int main(){
    //memset(head,-1,sizeof head);
    //memset(fa,-1,sizeof fa);
    int n;
    cin>>n;
    for(int i=1;i<n;i++){
        int u,v;
        scanf("%d%d",&u,&v);
        add(u,v);
        add(v,u);
    }
    dfs(1,0);
    int x,y;
    cin>>x>>y;
    int q;
    cin>>q;
    while(q--){
        int u,v;
        scanf("%d%d",&u,&v);
        int ans=dis(u,v);
        ans=min(ans,dis(u,x)+dis(v,y));
        ans=min(ans,dis(u,y)+dis(v,x));
        printf("%d\n",ans);
    }
    return 0;

}
题解 文章被收录于专栏

主要写一些题目的题解

全部评论

相关推荐

不愿透露姓名的神秘牛友
11-27 10:48
点赞 评论 收藏
分享
评论
点赞
收藏
分享
牛客网
牛客企业服务