[LOJ 2718][UOJ 393][BZOJ 5415][NOI 2018] return journey

Keywords: Python

[LOJ 2718][UOJ 393][BZOJ 5415] [NOI 2018] return journey

meaning of the title

Given an undirected graph, each edge has a distance and a height. Then given a group of \ (q \) possible online queries, each group of queries is given a point \ (v \) and a height \ (h \), duck Germany can first act on the edge with a height greater than \ (h \) without spending any money, and then can start to act at any point in a mode with a cost equal to the distance. Ask the minimum cost

\(|V|\le 2\times 10^5,|E|\le 4\times 10^5,q\le 4\times 10^5,h\le 10^9\).

Title Solution

Obviously the action with cost part is the shortest path of a single source. Then we only need to find out which point of the action without cost part can reach the closest distance \ (1 \)

It is found that the cost free part is similar to the bottleneck problem. We can multiply and find the subtree composed of the reachable points on the Kruskal reconstruction tree, and output the shortest distance from the points in the subtree to \ (1 \)

Why should I write the solution to this naked question?

One reason is the memory board, the other is that the sand sculpture forced me to card off \ (3 \) points of qaq online Specific circumstances

Reference code

#include <bits/stdc++.h>

const int MAXV=4e5+10;
const int MAXE=1e6+10;

struct Edge{
    int from;
    int to;
    int dis;
    int pos;
    Edge* next;
    bool friend operator>(const Edge& a,const Edge& b){
        return a.pos>b.pos;
    }
};
Edge E[MAXE];
Edge Ex[MAXE];
Edge* head[MAXV];
Edge* top=E;

int v;
int e;
int q;
int n;
int k;
int maxv;
int dis[MAXV];
int pos[MAXV];
int ufs[MAXV];
bool vis[MAXV];
int pprt[20][MAXV];
int* prt=pprt[0];

int ReadInt();
void Kruskal();
int FindRoot(int);
void Dijkstra(int);
void Insert(int,int,int,int);

int main(){
    int T=ReadInt();
    while(T--){
        memset(pprt,0,sizeof(pprt));
        memset(head,0,sizeof(head));
        memset(vis,0,sizeof(vis));
        top=E;
        n=v=ReadInt();
        e=ReadInt();
        for(int i=0;i<e;i++){
            int a=ReadInt(),b=ReadInt(),c=ReadInt(),d=ReadInt();
            Ex[i]=Edge({a,b,c,d,NULL});
            Insert(a,b,c,d);
            Insert(b,a,c,d);
        }
        q=ReadInt(),k=ReadInt(),maxv=ReadInt();
        Dijkstra(1);
        Kruskal();
        int lg=0;
        for(int i=1;(1<<i)<=v;i++){
            lg=i;
            for(int j=1;j<=v;j++)
                pprt[i][j]=pprt[i-1][pprt[i-1][j]];
        }
        int lastans=0;
        while(q--){
            int s=(0ll+ReadInt()+k*lastans-1)%n+1,h=(0ll+ReadInt()+k*lastans)%(maxv+1);
            for(int i=lg;i>=0;i--){
                if(pos[pprt[i][s]]>h)
                    s=pprt[i][s];
            }
            printf("%d\n",lastans=dis[s]);
        }
    }
    return 0;
}

void Kruskal(){
    std::sort(Ex,Ex+e,std::greater<Edge>());
    for(int i=1;i<=v;i++)
        ufs[i]=i;
    int& cur=v;
    for(int i=0;i<e;i++){
        int a=FindRoot(Ex[i].from);
        int b=FindRoot(Ex[i].to);
        if(a!=b){
            ++cur;
            pos[cur]=Ex[i].pos;
            dis[cur]=std::min(dis[a],dis[b]);
            prt[a]=cur;
            prt[b]=cur;
            ufs[cur]=cur;
            ufs[a]=cur;
            ufs[b]=cur;
        }
    }
}

void Dijkstra(int s){
    std::priority_queue<std::pair<int,int>> q;
    memset(dis,0x7F,sizeof(dis));
    dis[s]=0;
    q.emplace(0,s);
    while(!q.empty()){
        s=q.top().second;
        q.pop();
        if(vis[s])
            continue;
        vis[s]=true;
        for(Edge* i=head[s];i!=NULL;i=i->next){
            if(dis[i->to]>dis[s]+i->dis){
                dis[i->to]=dis[s]+i->dis;
                q.emplace(-dis[i->to],i->to);
            }
        }
    }
}

inline void Insert(int from,int to,int dis,int pos){
    top->from=from;
    top->to=to;
    top->dis=dis;
    top->pos=pos;
    top->next=head[from];
    head[from]=top++;
}

int FindRoot(int x){
    return ufs[x]==x?ufs[x]:ufs[x]=FindRoot(ufs[x]);
}

inline int ReadInt(){
    int x=0;
    register char ch=getchar();
    while(!isdigit(ch))
        ch=getchar();
    while(isdigit(ch)){
        x=x*10+ch-'0';
        ch=getchar();
    }
    return x;
}

Posted by Naoa on Fri, 01 Nov 2019 16:43:44 -0700