ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

NC19814 最短路(LCA+思维)

2021-02-17 19:33:43  阅读:128  来源: 互联网

标签:cnt int 短路 LCA NC19814 depth lca dis


这题如果注意到m的范围,那么思路将会豁然开朗

因为如果是一棵树,那么直接lca就能求得两点间最小值

但是现在是图,并且边数就比一棵树大100左右

所以我们可以想到,先将图中取出生成树,用lca求答案

那么剩下就有100条边左右未使用,我们发现,答案可能经过这些边,因此我们枚举这些边的端点去做01最短路,对两种情况取min就是最后答案

直接做最短路的正确性在于,如果答案使用到了某条未在树上的边,那么我们因为使用了这条边做最短路,因此我们求得的一定是通过这条边相关的最短距离

因此枚举全部就能获得答案

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<ll,ll> pll;
const int N=1e5+200;
const int mod=1e9+7;
int h[N],ne[N<<1],e[N<<1],idx,cnt;
bool st[N<<1],pos[N],used[N<<1];
int n,m;
int lg[N<<1];
int depth[N],f[N][25],dis[210][N],from[N<<1],to[N<<1];
void add(int a,int b){
    e[idx]=b,ne[idx]=h[a],h[a]=idx++;
}
void dfs(int u,int fa){
    depth[u]=depth[fa]+1;
    st[u]=1;
    f[u][0]=fa;
    int i;
    for(i=1;i<lg[depth[u]];i++){
        f[u][i]=f[f[u][i-1]][i-1];
    }
    for(i=h[u];i!=-1;i=ne[i]){
        int j=e[i];
        if(st[j])
            continue;
        used[i]=used[i^1]=1;
        dfs(j,u);
    }
}
void bfs(int s){
    int i;
    cnt++;
    for(i=0;i<=n;i++){
        dis[cnt][i]=0x3f3f3f3f;
        st[i]=0;
    }
    dis[cnt][s]=0;
    queue<int> q;
    q.push(s);
    while(q.size()){
        int t=q.front();
        q.pop();
        if(st[t])
            continue;
        st[t]=1;
        for(i=h[t];i!=-1;i=ne[i]){
            int j=e[i];
            if(dis[cnt][j]>dis[cnt][t]+1){
                dis[cnt][j]=dis[cnt][t]+1;
                q.push(j);
            }
        }
    }
}
int lca(int a,int b){
    if(depth[a]<depth[b])
        swap(a,b);
    int i;
    for(i=21;i>=0;i--){
        if(depth[f[a][i]]>=depth[b]){
            a=f[a][i];
        }
    }
    if(a==b)
        return a;
    for(i=21;i>=0;i--){
        if(f[a][i]!=f[b][i]){
            a=f[a][i];
            b=f[b][i];
        }
    }
    return f[a][0];
}
int main(){
    //ios::sync_with_stdio(false);
    memset(h,-1,sizeof h);
    cin>>n>>m;
    int i;
    for(i=1;i<=n;i++)
        lg[i]=lg[i-1]+(i==(1<<lg[i-1]));
    for(i=1;i<=m;i++){
        int a,b;
        scanf("%d%d",&a,&b);
        from[idx]=a;
        add(a,b);
        from[idx]=b;
        add(b,a);
    }
    st[0]=1;
    dfs(1,0);
    for(i=0;i<idx;i+=2){
        if(used[i])
            continue;
        used[i]=used[i^1]=1;
        if(!pos[from[i]]){
            pos[from[i]]=1;
            bfs(from[i]);
        }
    }
    int q;
    cin>>q;
    while(q--){
        int a,b;
        scanf("%d%d",&a,&b);
        int ans;
        ans=depth[a]+depth[b]-2*depth[lca(a,b)];
        for(i=1;i<=cnt;i++)
            ans=min(ans,dis[i][a]+dis[i][b]);
        printf("%d\n",ans);
    }
    return 0;
}
View Code

 

标签:cnt,int,短路,LCA,NC19814,depth,lca,dis
来源: https://www.cnblogs.com/ctyakwf/p/14409492.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有