Logu P4768 [NOI2018] trip (Kruskal refactoring tree)

Posted by shibiny on Sat, 01 Feb 2020 18:23:53 +0100

meaning of the title

Look directly at the topic, it's not descriptive

Sol

Consider violent practices

First, the shortest path from $1 to each node is preprocessed.

For each question, the violent BFS takes $min from the point it can walk to.

Consider how to optimize, using Kruskal refactoring tree here

We constructed a Kruskal refactoring tree by sorting the elevation of the edge right from large to small

This must be a small heap

The minimum altitude at which nodes in a point's subtree can reach each other is the weight of that point.

So every time we query, we just need to double how much we can go up from this point to meet the criteria

Then look inside the subtree for the maximum of $1 per point.

 

Alas, I haven't pulled it out all morning, only 72 points, can pass all the individual data, but running together is GG, and my local big data is RE.

It doesn't make any sense to keep it down. Wait a day when you're in a good mood and rewrite it.

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<queue>
//#define int long long 
#define MP(x, y) make_pair(x, y)
#define Pair pair<int, int> 
using namespace std;
const int MAXN = 1e6 + 10, INF = 2147483646, B = 19;
inline int read() {
    char c = getchar(); int x = 0, f = 1;
    while(c < '0' || c > '9') {if(c == '-') f = 1; c = getchar();}
    while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
    return x * f;
}
int QwQ, N, M;
struct Edge {
    int u, v, l, a, nxt;
    bool operator < (const Edge &rhs) const {
        return a > rhs.a;//Small root heap 
    }
}E[MAXN << 1];
int head[MAXN], num = 0;
inline void AddEdge(int x, int y, int z, int gg) {
    E[num] = (Edge){x, y, z, gg, head[x]};
    head[x] = num++;
}
inline void work() {
    N = read(); M = read();
    for(int i = 1; i <= M; i++) {
        int u = read(), v = read(), l = read(), a = read();
        AddEdge(u, v, l, a); AddEdge(v, u, l, a);
    }
}

int vis[MAXN], dis[MAXN];
void MinDisRood() {//Find the shortest path from 1 to each node 
    memset(dis, 0x3f, sizeof(dis));
    memset(vis, 0, sizeof(vis));
    priority_queue<Pair> q;
    dis[1] = 0; q.push(MP(0, 1));
    while(!q.empty()) {
        while(!q.empty() && vis[q.top().second]) q.pop();
        int p = q.top().second; vis[p] = 1;
        for(int i = head[p]; i != -1; i = E[i].nxt) {
            int to = E[i].v;
            if(dis[to] > dis[p] + E[i].l && !vis[to]) {
                dis[to] = dis[p] + E[i].l;
                q.push(MP(-dis[to], to));
            }
        }
    }
}
int fa[MAXN], cnt, g[MAXN][21], f[MAXN][21], ch[MAXN][21], val[MAXN];
int find(int x) {
    if(fa[x] == x) return fa[x];
    else return fa[x] = find(fa[x]);
}
void Kruskal() {
    cnt = N;
    for(int i = 1; i <= 2 * N; i++)  fa[i] = i;
    sort(E, E + num + 1);
    for(int i = 0; i <= num; i++) {
        int fx = find(E[i].u), fy = find(E[i].v);
        if(fx == fy) continue;
        ch[++cnt][0] = fx; ch[cnt][1] = fy;
        fa[fx] = fa[fy] = cnt; 
        val[cnt] = E[i].a;
        g[fx][0] = g[fy][0] = val[cnt];
        f[fx][0] = f[fy][0] = cnt;
    }
}
int mi[MAXN];
int dfs(int x) {
    mi[x] = INF;
    if(!ch[x][0] && !ch[x][1]) return mi[x] = dis[x];
    mi[x] = min(mi[x], dfs(ch[x][0]));
    mi[x] = min(mi[x], dfs(ch[x][1]));
    return mi[x];
}
void Pre() {
    for(int j = 1; j <= B; j++) 
        for(int i = 1; i <= 2 * N; i++)
            f[i][j] = f[f[i][j - 1]][j - 1], 
            g[i][j] = min(g[i][j - 1], g[f[i][j - 1]][j - 1]);    
    dfs(cnt);
}
int Find(int bg, int val) {//from bg Jump off the net and find an elevation greater than val The smallest point 
    for(int i = B; i >= 0; i--)
        if(g[bg][i] > val && g[bg][i] <= INF)
            bg = f[bg][i];
    return bg;
}
void DealQuery() {
    int Q = read(), K = read(), S = read(), lastans = 0;
    while(Q--) {
        int v = read(), p = read();
        v = (v + K * lastans - 1) % N + 1;
        p = (p + K * lastans) % (S + 1);
        printf("%d\n", lastans = mi[Find(v, p)]);
    }
}
inline void init() {
    memset(g, 0x3f, sizeof(g));
    memset(val, 0, sizeof(val));
    memset(head, -1, sizeof(head)); 
    memset(ch, 0, sizeof(ch));
    memset(mi, 0, sizeof(mi));
    memset(f, 0, sizeof(f));
    num = 0;
}
main() {
    QwQ = read();
    while(QwQ--) {
        init();
        work();
        //if(N != 1500 || M != 2922) continue;
        MinDisRood();
        Kruskal();
        Pre();
        DealQuery();
    }
    return 0;
}

Topics: C++ Big Data