【BZOJ2725】【Violet 6】故乡的梦

【题目链接】

【思路要点】

  • 补档博客,无题解。

【代码】

#include<bits/stdc++.h>
using namespace std;
#define MAXN	200005
#define INF	1e18
template <typename T> void read(T &x) {
	x = 0; int f = 1;
	char c = getchar();
	for (; !isdigit(c); c = getchar()) if (c == '-') f = -f;
	for (; isdigit(c); c = getchar()) x = x * 10 + c - '0';
	x *= f;
}
struct Segment_Tree {
	int n, size, root;
	int lc[MAXN * 2], rc[MAXN * 2];
	long long tag[MAXN * 2];
	int new_node() {
		tag[size] = INF;
		return size++;
	}
	void build(int root, int l, int r) {
		if (l == r) return;
		int mid = (l + r) / 2;
		lc[root] = new_node();
		build(lc[root], l, mid);
		rc[root] = new_node();
		build(rc[root], mid + 1, r);
	}
	void init(int x) {
		n = x;
		size = 0;
		root = new_node();
		build(root, 1, n);
	}
	void modify(int root, int l, int r, int ql, int qr, long long value) {
		if (l == ql && r == qr) {
			tag[root] = min(tag[root], value);
			return;
		}
		int mid = (l + r) / 2;
		if (mid >= ql) modify(lc[root], l, mid, ql, min(qr, mid), value);
		if (mid + 1 <= qr) modify(rc[root], mid + 1, r, max(mid + 1, ql), qr, value);
	}
	void modify(int l, int r, long long value) {
		if (l <= r) modify(root, 1, n, l, r, value);
	}
	long long query(int root, int l, int r, int x) {
		if (l == r) return tag[root];
		int mid = (l + r) / 2;
		if (mid >= x) return min(tag[root], query(lc[root], l, mid, x));
		else return min(tag[root], query(rc[root], mid + 1, r, x));
	}
	long long query(int x) {
		return query(root, 1, n, x);
	}
} ST;
struct edge {int dest, len; };
struct info {long long value; int pos, home; };
int n, m, s, t, pred[MAXN], succ[MAXN];
int x[MAXN], y[MAXN], z[MAXN], num[MAXN];
vector <edge> a[MAXN];
vector <int> b[MAXN];
priority_queue <info> Heap;
long long dist[MAXN], cist[MAXN];
bool mark[MAXN];
bool operator < (info a, info b) {return a.value > b.value; }
bool on_road(int x, int y) {
	return mark[x] && mark[y] && (succ[x] == y || succ[y] == x);
}
void work(int pos, int value) {
	num[pos] = value;
	for (unsigned i = 0; i < b[pos].size(); i++)
		if (num[b[pos][i]] == 0) work(b[pos][i], value);
}
int main() {
	read(n), read(m);
	for (int i = 1; i <= m; i++) {
		read(x[i]), read(y[i]), read(z[i]);
		a[x[i]].push_back((edge) {y[i], z[i]});
		a[y[i]].push_back((edge) {x[i], z[i]});
	}
	read(s), read(t);
	for (int i = 1; i <= n; i++)
		dist[i] = cist[i] = INF;
	dist[s] = 0;
	Heap.push((info) {0, s, 0});
	while (!Heap.empty()) {
		while (!Heap.empty() && mark[Heap.top().pos]) Heap.pop();
		if (Heap.empty()) break;
		info tmp = Heap.top();
		Heap.pop(); mark[tmp.pos] = true;
		pred[tmp.pos] = tmp.home;
		for (unsigned i = 0; i < a[tmp.pos].size(); i++)
			if (tmp.value + a[tmp.pos][i].len < dist[a[tmp.pos][i].dest]) {
				dist[a[tmp.pos][i].dest] = tmp.value + a[tmp.pos][i].len;
				Heap.push((info) {dist[a[tmp.pos][i].dest], a[tmp.pos][i].dest, tmp.pos});
			}
	}
	if (dist[t] == INF) {
		int q; read(q);
		for (int i = 1; i <= q; i++)
			printf("Infinity\n");
		return 0;
	}
	memset(mark, 0, sizeof(mark));
	cist[t] = 0;
	Heap.push((info) {0, t, 0});
	while (!Heap.empty()) {
		while (!Heap.empty() && mark[Heap.top().pos]) Heap.pop();
		if (Heap.empty()) break;
		info tmp = Heap.top();
		Heap.pop(); mark[tmp.pos] = true;
		for (unsigned i = 0; i < a[tmp.pos].size(); i++)
			if (tmp.value + a[tmp.pos][i].len < cist[a[tmp.pos][i].dest]) {
				cist[a[tmp.pos][i].dest] = tmp.value + a[tmp.pos][i].len;
				Heap.push((info) {cist[a[tmp.pos][i].dest], a[tmp.pos][i].dest, tmp.pos});
			}
	}
	memset(mark, 0, sizeof(mark));
	int pos = t;
	while (pos) {
		mark[pos] = true;
		succ[pred[pos]] = pos;
		pos = pred[pos];
	}
	int cnt = 0; pos = s;
	while (pos) {
		num[pos] = ++cnt;
		pos = succ[pos];
	}
	for (int i = 1; i <= n; i++)
		b[pred[i]].push_back(i);
	for (int i = 1; i <= n; i++)
		if (num[i]) work(i, num[i]);
	ST.init(cnt);
	for (int i = 1; i <= m; i++)
		if (!on_road(x[i], y[i])) {
			if (num[x[i]] > num[y[i]]) swap(x[i], y[i]);
			ST.modify(num[x[i]], num[y[i]] - 1, dist[x[i]] + z[i] + cist[y[i]]);
		}
	int q; read(q);
	for (int i = 1; i <= q; i++) {
		int x, y;
		read(x), read(y);
		if (!on_road(x, y)) printf("%lld\n", dist[t]);
		else {
			if (num[x] > num[y]) swap(x, y);
			long long tmp = ST.query(num[x]);
			if (tmp == INF) printf("Infinity\n");
			else printf("%lld\n", tmp);
		}
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_39972971/article/details/80039241