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; }