【SEERC2022】 K.Knowledge Testing Problem 【整体二分】【最短路】

分析:注意到$|u-v|<=10$,所以可以将询问的最短路分类为,左边的最短路,跨越左右的最短路,右边的最短路。套整体二分的板子就行。以前应该做过

代码:

#include<bits/stdc++.h>
using namespace std;

const int maxn = 102000;

typedef pair<long long,int> pr;

int n,m,qy;
struct node{
    int to,w;
};
struct query{
    int u,v,pos;
}q[maxn],nq[maxn];
vector<node> g[maxn];
long long dis[12][maxn];
int vis[maxn];
long long ans[maxn];

priority_queue<pr,vector<pr>,greater<pr> > pq;
void dijkstra(int s,long long *dist,int l,int r){
    for(int i=l;i<=r;i++) dist[i] = 1e17,vis[i] = 0;
    dist[s] = 0;
    pq.push(make_pair(0,s));
    while(!pq.empty()){
    pr k = pq.top();pq.pop();
    if(vis[k.second]) continue;
    vis[k.second] = 1;
    for(auto x:g[k.second]){
        if(dist[x.to] > dist[k.second]+x.w){
        dist[x.to] = dist[k.second]+x.w;
        pq.push(make_pair(dist[x.to],x.to));
        }
    }
    }
}

void Divide(int l,int r,int ql,int qr){
    if(ql > qr) return;
    if(r-l <= 10){
    for(int i=l;i<=r;i++){
        dijkstra(i,dis[i-l],l,r);
    }
    for(int i=ql;i<=qr;i++){
        int pos = q[i].pos;
        for(int j=0;j<=r-l;j++){
        ans[pos]=min(ans[pos],dis[q[i].u-l][q[i].v]);
        }
    }
    }else{
    int mid = (l+r)/2;
    int fl = mid-5,fr = mid+5;
    for(int i=fl;i<=fr;i++){
        dijkstra(i,dis[i-fl],l,r);
            //range in [fl,r] source is i, load in i-fl
    }
    for(int i=l;i<fl;i++){
        for(int j=0;j<g[i].size();j++){
        if(g[i][j].to >= fl){
            swap(g[i][j],g[i][g[i].size()-1]);
            g[i].pop_back();
            j--;
        }
        }
    }
    for(int i=fl;i<=fr;i++) g[i].clear();
    for(int i=fr+1;i<=r;i++){
        for(int j=0;j<g[i].size();j++){
        if(g[i][j].to <= fr){
            swap(g[i][j],g[i][g[i].size()-1]);
            g[i].pop_back();
            j--;
        }
        }
    }
    int dl=ql-1,dr=qr+1;
    for(int i=ql;i<=qr;i++){
        for(int j=fl;j<=fr;j++){
        ans[q[i].pos] = min(ans[q[i].pos],dis[j-fl][q[i].u]+dis[j-fl][q[i].v]);
        }
        if(q[i].v < fl) nq[++dl] = q[i];
        if(q[i].u > fr) nq[--dr] = q[i];
    }
    for(int i=ql;i<=qr;i++) q[i] = nq[i];
    Divide(l,fl-1,ql,dl);
    Divide(fr+1,r,dr,qr);
    }
}

int main(){
    ios::sync_with_stdio(false);
    cin.tie(0); cout.tie(0);
    cin >> n >> m >> qy;
    memset(ans,127/3,sizeof(ans));
    for(int i=1;i<=m;i++){
    int u,v,w; cin >> u >> v >> w;
    g[u].push_back((node){v,w});
    g[v].push_back((node){u,w});
    }
    for(int i=1;i<=qy;i++) {
    cin >> q[i].u >> q[i].v;
    if(q[i].u > q[i].v) swap(q[i].u,q[i].v);
    q[i].pos = i;
    }
    Divide(1,n,1,qy);
    for(int i=1;i<=qy;i++){
    if(ans[i] > 1e15) cout<<"-1\n";
    else cout<<ans[i]<<"\n";
    }
    return 0;
}

 

posted @ 2022-12-24 17:54  menhera  阅读(114)  评论(0编辑  收藏  举报