[LG5304] [GXOI / GZOI2019] travelers

Title effect: with a \ (n (n \ leqslant10 ^ 5) \) points \ (m (m \ leqslant5 \ times10 ^ 5) \) have edges to the positive weighted graph with $ k (2 \ leqslant k \ leqslant n) $ key points. He asked the figure closest two key points. Multiple sets of data.

Solution: There are two ways.

  1. $ K $ may be of critical points binary packet can know the $ X $ $ $ Y satisfy at least have a different binary different, each press of a binary divided into two groups,, to build a virtual point connected to all source, run \ (Dijkstra \) , ran a total of \ (log_2n \ \) times. Complexity \ (O (n-\ ^ log_2 2N) \) . I did not write the code

  2. So \ (F_i \) represents can go to the nearest point of the key points of the $ i $, \ (F_i \) to \ (dis_ {F_i, i} \) , \ (T_i \) represents the $ i $ points You may come the closest key point, \ (t_i \) to \ (dis_ i.T_i} {\) . ~ ~ Get a solution to a problem, an edge enumerate ~~ \ ((U, v, w) \) , if \ (F_u \ not = T_v \) , then use \ (f_u + w + t_v \ ) update the answer. These arrays may be run in reverse to FIG all key source point to obtain the shortest path. Next to prove why it is so right.

    Clearly can be shown, if the shortest path \ (X \ to Y \) , wherein the edge \ ((u, v, w ) \) and on this path \ (F_u \ Not = T_v \) , then the \ ( X = f_u, T_v = Y \) (assuming only one shortest path), then \ (f_u + W + T_V ANS = \) . That is, if they can prove $ x \ to the path y $ has at least one edge to meet the $ F_u \ not = T_v $

    Method disprove. FIG follows an example in which $ 1 \ to n $ is the shortest path, square dots critical point, the edge weights are provided $ $ W

    graph LR; A[1] B((2)) C((3)) D((n-1)) E[n] A--A-->B B--B-->C C-.-D D--Z-->E

    For the side for $ A $, \ (F_u = 1, the n-T_v = \) , to destroy as $ F_u $ can not change, only change $ T_v $, may be even a $ 2 \ to 1 $ sides, the right side less than $ w $, $ A $ then the side will not be able to generate contributions to the answers. $ B side consider $, \ (= F_u. 1, n-T_v = \) , to destroy, there are two methods, one is even a $ n \ to the right side is less than 2 $ $ $ W side, another species are even a $ 3 \ to the right edge is less than $ 1 $ $ W side. Since the first embodiment will produce a $ n \ to 2 \ to 1 $ shorter path, it is drained, with only a second. And so, eventually even a $ n \ to 1 $ sides led to the emergence of a shorter path. Contradiction with the original hypothesis. Therefore, the original proposition is true

Card point: None

C++ Code:

#include <iostream>
#include <algorithm>
#include <cstring>
#define maxn 100010
#define maxm 500010

int cnt, head[maxn], _head[maxn];
struct Edge {
	int to, nxt, w;
} e[maxm], _e[maxm];
inline 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;
}

int Tim, n, m, k;
int To[maxn], _To[maxn];
long long dis[maxn], _dis[maxn];
bool mar[maxn];

namespace Graph {
	int V[maxn << 2];
	long long *Dis;

	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 num) {
		if (l == r) {
			V[rt] = num;
			return ;
		}
		const int mid = l + r >> 1;
		if (p <= mid) modify(rt << 1, l, mid, p, num);
		else modify(rt << 1 | 1, mid + 1, r, p, num);
		V[rt] = getmin(V[rt << 1], V[rt << 1 | 1]);
	}

	void dijkstra(int *head, Edge *e, int *To, long long *dis) {
		const int SZ = maxn << 3;
		memset(dis, 0x3f, SZ);
		Dis = dis;
		memset(V, 0, sizeof V);
		for (int i = 1; i <= n; ++i) To[i] = i;
		for (int i = 1; i <= n; ++i) if (mar[i]) {
			dis[i] = 0;
			modify(1, 1, n, i, i);
		}
		for (int Tim = n; Tim; --Tim) {
			int u = V[1];
			modify(1, 1, n, u, 0);
			for (int i = head[u]; i; i = e[i].nxt) {
				int v = e[i].to;
				if (dis[v] > dis[u] + e[i].w) {
					dis[v] = dis[u] + e[i].w;
					To[v] = To[u];
					modify(1, 1, n, v, v);
				}
			}
		}
	}
}
using Graph::dijkstra;

int main() {
	std::ios::sync_with_stdio(false), std::cin.tie(0), std::cout.tie(0);
	std::cin >> Tim;
	while (Tim --> 0) {
		std::cin >> n >> m >> k;
		for (int i = 0, a, b, c; i < m; ++i) {
			std::cin >> a >> b >> c;
			addedge(a, b, c);
		}
		memset(mar, false, sizeof mar);
		for (int i = 0, x; i < k; ++i) std::cin >> x, mar[x] = true;
		dijkstra(_head, _e, To, dis);
		dijkstra(head, e, _To, _dis);
		long long ans = 0x3f3f3f3f3f3f3f3f;
		for (int i = 1, u, v; i <= m; ++i) {
			u = _e[i].to, v = e[i].to;
			if (_To[u] != To[v]) ans = std::min(ans, _dis[u] + e[i].w + dis[v]);
		}
		std::cout << ans << '\n';
		if (Tim) {
			memset(head, 0, sizeof head);
			memset(_head, 0, sizeof _head);
			cnt = 0;
		}
	}
	return 0;
}

Guess you like

Origin www.cnblogs.com/Memory-of-winter/p/11071827.html