小A的最短路 解题报告(LCA,最短路)

小A的最短路

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

首先,题目有个条件: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;
}
全部评论

相关推荐

时间线:&nbsp;1.4-1.5:&nbsp;boss&nbsp;牛客&nbsp;官网&nbsp;实习僧海投了两天,&nbsp;感觉确实没啥招人的啊,&nbsp;心里凉了一半.1.6:&nbsp;中午快手约面,&nbsp;下午字节hr飞书私聊约面,&nbsp;当时想着第一次面大厂感觉三个过一个一面就已经赢了.1.7:&nbsp;下午&nbsp;3点大厂处女面,&nbsp;哈哈面试官是重邮红岩的直接保送;&nbsp;5点快手一面,&nbsp;我说这个是我的第二次大厂面试,&nbsp;面试官问要是拿到字节和快手选择哪个,&nbsp;我说昨天看了一晚上快手百分百选快手哈哈哈.&nbsp;晚上5.30字节约二面,&nbsp;快手约二面,&nbsp;小红书约一面.1.8:&nbsp;下午2点快手二面,&nbsp;聊天面体验非常好(当天电话确认入职时间);&nbsp;4点字节二面这次不是校友了,&nbsp;然后有一个CSS实现switch效果的忘记属性咋写了,&nbsp;感觉危了;&nbsp;7.30&nbsp;问字节hr是不是挂了;&nbsp;9点开始小红书一面,&nbsp;难死我了,&nbsp;但我还是笑着面完了,&nbsp;然后卸载了小红书,&nbsp;但是过了一会会小红书hr约二面,&nbsp;遂下回来了字节约三面.1.9:&nbsp;下午2点字节三面,&nbsp;依旧聊天+算法,&nbsp;自己太菜了有一个写错了,&nbsp;面完感觉又危了;&nbsp;5点面小红书20min结束(offer审批);5.30又去问字节hr是不是挂了,&nbsp;hr小姐姐说干嘛用一个句式,&nbsp;我说手写题又又又没写出来😂,&nbsp;2min后约hr面;8.30&nbsp;快手offer总结,&nbsp;自己运气好遇到了好公司好部门好面试官,&nbsp;字节剪映&nbsp;快手电商&nbsp;小红书支付的面试体验都非常好,&nbsp;不会的题会带你一步一步思考,&nbsp;流程也非常快全部都是当天推进,&nbsp;小红书是以分钟为单位推进.&nbsp;&nbsp;面经以及细节等我慢慢整理,&nbsp;&nbsp;以及保佑所有的审批不要出问题,&nbsp;我是真怕最后全过了0offer😂bg:&nbsp;重邮&nbsp;大数据&nbsp;蓝山工作室&nbsp;一段非大厂实习
独角仙梦境:这是真👻了
找实习记录
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务