[UOJ #393]【NOI2018】归程

题目大意:有一张$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;
}

  

猜你喜欢

转载自www.cnblogs.com/Memory-of-winter/p/11628351.html