题目大意:有一张$n$个点$m$条边的图,每个边有两个属性$a_i,b_i$。有$Q$个询问,每个询问给出$v,p$,表示所有边中$b_i\leqslant p$的边会被标记,在点$v$,可以通过不被标记的边到达任意点,然后用最小的$\sum a_i$到达点$1$,输出这个最小值。多组数据
$n\leqslant2\times10^5,m\leqslant4\times10^5$,最多$3$组数据。
题解:$\mathrm{kruskal}$重构树,按$b_i$从大到小建重构树,可以发现若一个点没有被标记,它的子树内均不被标记,所以可以由点$1$跑最短路,然后记录每个节点的子树内最近的值。注意,$\mathrm{SPFA}$已死,要用$\mathrm{dijkstra}$。
卡点:多组数据中清空错误
C++ Code:
#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> const int maxn = 6e5 + 10; int Tim, n, m, N, Q, K, S, f[maxn], w[maxn]; int _u[maxn], _v[maxn], _l[maxn], _a[maxn], rnk[maxn]; inline bool cmp(int a, int b) { return _a[a] > _a[b]; } int find(int x) { return x == f[x] ? x : (f[x] = find(f[x])); } long long dis[maxn]; namespace Graph { int head[maxn], cnt; struct Edge { int to, nxt, w; } e[maxn << 1]; void addedge(int a, int b, int c) { e[++cnt] = (Edge) { b, head[a], c }; head[a] = cnt; e[++cnt] = (Edge) { a, head[b], c }; head[b] = cnt; } void clear() { memset(head, 0, sizeof head), cnt = 0; } int V[maxn << 2]; inline int getmin(int a, int b) { return dis[a] < dis[b] ? a : b; } void modify(int rt, int l, int r, int p, int v) { if (l == r) { V[rt] = v; return ; } int mid = l + r >> 1; if (p <= mid) modify(rt << 1, l, mid, p, v); else modify(rt << 1 | 1, mid + 1, r, p, v); V[rt] = getmin(V[rt << 1], V[rt << 1 | 1]); } void dijkstra(int S) { memset(dis, 0x3f, sizeof dis), memset(V, 0, sizeof V); dis[S] = 0, modify(1, 1, n, S, S); for (int Tim = n; Tim; --Tim) { int u = V[1]; modify(1, 1, n, u, 0); for (int i = head[u], v; i; i = e[i].nxt) { v = e[i].to; if (dis[v] > dis[u] + e[i].w) dis[v] = dis[u] + e[i].w, modify(1, 1, n, v, v); } } } } const int M = 24; int fa[maxn][M + 1]; void addedge(int a, int b) { fa[b][0] = a, dis[a] = std::min(dis[a], dis[b]); } long long query(int v, int p) { for (int i = M; ~i; --i) if (w[fa[v][i]] > p) v = fa[v][i]; return dis[v]; } int main() { std::ios::sync_with_stdio(false), std::cin.tie(0), std::cout.tie(0); std::cin >> Tim; while (Tim --> 0) { Graph::clear(), w[0] = -0x3f3f3f3f, memset(fa, 0, sizeof fa); std::cin >> n >> m, N = n; for (int i = 0, l; i < m; ++i) { std::cin >> _u[i] >> _v[i] >> l >> _a[i]; Graph::addedge(_u[i], _v[i], l); rnk[i] = i; } Graph::dijkstra(1); for (int i = 1; i <= n + m; ++i) f[i] = i; std::sort(rnk, rnk + m, cmp); for (int i = 0, u, v; i < m; ++i) { u = find(_u[rnk[i]]), v = find(_v[rnk[i]]); if (u != v) { addedge(++N, u), addedge(N, v); w[N] = _a[rnk[i]], f[u] = f[v] = N; } } for (int i = 1; i <= M; ++i) for (int j = 1; j <= N; ++j) fa[j][i] = fa[fa[j][i - 1]][i - 1]; std::cin >> Q >> K >> S; long long v, p, ans = 0; while (Q --> 0) { std::cin >> v >> p; if (K) v = (v + ans - 1) % n + 1, p = (p + ans) % (S + 1); ans = query(v, p); std::cout << ans << '\n'; } } return 0; }