zoukankan      html  css  js  c++  java
  • NC19814 最短路(LCA+思维)

    这题如果注意到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
    ",ans);
        }
        return 0;
    }
    View Code
    没有人不辛苦,只有人不喊疼
  • 相关阅读:
    LOG4J介绍
    基于AspectJ的XML方式进行AOP开发
    tsdb import 相关
    xming + putty remote GUI
    html5 编辑
    swift container server 莫名stuck
    rsyslog trouble shooting
    文件处理 字符串处理
    list去掉重复元素
    找到字符串中最长的回文
  • 原文地址:https://www.cnblogs.com/ctyakwf/p/14409492.html
Copyright © 2011-2022 走看看