zoukankan      html  css  js  c++  java
  • 2021浙江省大学生程序设计竞赛D题 Shortest Path Query(最短路+思维)

    这道题我们肯定敏锐的观察到题目的一个特殊性质

    只有一个数是另一个数的二进制前缀才能连边,这个性质肯定要用到,等会我们来思考。

    首先是暴力算法,假设要知道两两点的最短路,最暴力的想法就是求floyd,这个太夸张了,我们显然可以放弃掉。

    之后就是对于每个点求迪杰斯特拉,这个算法做一次复杂度过关,但是做多次在普通的图上显然是超时算法。

    这下就用到了题目给的性质。对于一些点,不管他们是什么,如果他们的前缀相同,那么他们就有一些共同的父亲节点,假设可以到达的话。

    我们没有办法存在每个点到任意点的距离,但是我们可以存他们到父亲点的距离,因为前缀没几个。对于这个特殊的图,两点之间可达,一定是有前缀相同

    因此我们可以枚举这个前缀,按照lca的思路,分别是他们到前缀的路径和的最小值。

    这样只要对每个点跑迪杰斯特拉求这些值就行了。

    对每个点跑迪杰斯特拉的正确性在于,我们每次只更新的小的点往大的点的这些路径。对于每个点,他的扩展有01两种情况,因此均摊下来,对于每个以他为根的子图当中的点差不多是log级别,可以接受。

    但是注意每次不能把所有信息的清空,需要遇到一个清空一个。

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    typedef pair<ll,int> pll;
    const int N=2e5+10;
    const int M=2e6+10;
    int n,m;
    int h[N],ne[M],e[M],w[M],idx;
    ll dis[N][20];
    int st[N],vis[N];
    ll d[N];
    void add(int a,int b,int c){
        e[idx]=b,ne[idx]=h[a],w[idx]=c,h[a]=idx++;
    }
    int cal(int u,int v){
        int cnt=0;
        while(v>u){
            v>>=1;
            cnt++;
        }
        return cnt;
    }
    void dij(int rt){
        priority_queue<pll,vector<pll>,greater<pll>> q;
        q.push({0,rt});
        d[rt]=0;
        vis[rt]=rt;
        while(q.size()){
            auto t=q.top();
            q.pop();
            if(st[t.second]==rt)
                continue;
            st[t.second]=rt;
            dis[t.second][cal(rt,t.second)]=d[t.second];
            for(int i=h[t.second];i!=-1;i=ne[i]){
                int j=e[i];
                if(j<rt)
                    continue;
                if(vis[j]!=rt){
                    vis[j]=rt;
                    d[j]=1e16;
                }
                if(d[j]>d[t.second]+w[i]){
                    d[j]=d[t.second]+w[i];
                    q.push({d[j],j});
                }
            }
        }
    }
    int lca(int a,int b){
        while(a!=b){
            if(a>b)
                a>>=1;
            else
                b>>=1;
        }
        return min(a,b);
    }
    int getsz(int u){
        int cnt=0;
        while(u){
            cnt++;
            u>>=1;
        }
        return cnt;
    }
    int main(){
        ios::sync_with_stdio(false);
        memset(h,-1,sizeof h);
        cin>>n>>m;
        int i,j;
        for(i=1;i<=n;i++){
            for(j=0;j<=19;j++){
                dis[i][j]=1e16;
            }
        }
        for(i=1;i<=n;i++){
            dis[i][0]=0;
        }
        for(i=1;i<=m;i++){
            int a,b,c;
            cin>>a>>b>>c;
            add(a,b,c);
            add(b,a,c);
        }
        for(i=1;i<=n;i++){
            dij(i);
        }
        int q;
        cin>>q;
        while(q--){
            int a,b;
            cin>>a>>b;
            int p=lca(a,b);
            int l1=getsz(a)-getsz(p);
            int l2=getsz(b)-getsz(p);
            ll ans=1e16;
            while(p){
                ans=min(ans,dis[a][l1]+dis[b][l2]);
                l1++,l2++;
                p>>=1;
            }
            if(ans==1e16)
                cout<<-1<<endl;
            else
                cout<<ans<<endl;
        }
        return 0;
    }
    View Code
    没有人不辛苦,只有人不喊疼
  • 相关阅读:
    curl发送post请求,统计响应时间
    云集微店、拼多多等顽疾凸显,社交电商如何突围?
    App音频内录 录音
    nginx支持android、ios、微信扫一扫
    hadoop 2.7.1安装和配置
    Centos7上HBase的安装和配置
    HBase各版本对Hadoop版本的支持情况
    40个Java多线程问题总结
    JAVA多线程之volatile 与 synchronized 的比较
    深入解析spring中用到的九种设计模式
  • 原文地址:https://www.cnblogs.com/ctyakwf/p/14731099.html
Copyright © 2011-2022 走看看