[luogu P6348] [PA2011]Journeys

[luogu P6348] [PA2011]Journeys

题解

最直接的做法就是直接连边然后跑01最短路
但是边数特别多,所以要线段树优化建边
要注意的一点是双向边必须建两对点来辅助
不能直接只建一对点,不然会出现自己到自己的情况
code:

#include<bits/stdc++.h>
#define N 8000005
using namespace std;
struct edge {
	int v, nxt, c;
} e[N << 1];
int p[N], eid;
void init() {
	memset(p, -1, sizeof p);
	eid = 0;
}
void add(int u, int v, int c) {// printf("%d ---> %d  %d\n", u, v, c);
	e[eid].v = v;
	e[eid].c = c;
	e[eid].nxt = p[u];
	p[u] = eid ++;
}
int ch[N << 1][2], id[N], vis[N], n, m, cap, dis[N], tot;
void build(int &rt, int &rtt, int l, int r) {
	rtt = rt = ++ tot;
	if(l != r) rtt = ++ tot;
	if(l == r) {
		id[l] = rt;
		return;
	}
	int mid = (l + r) >> 1;
	build(ch[rt][0], ch[rtt][0], l, mid),
	build(ch[rt][1], ch[rtt][1], mid + 1, r);
	add(rt, ch[rt][0], 0), add(rt, ch[rt][1], 0),
	add(ch[rtt][0], rtt, 0), add(ch[rtt][1], rtt, 0);
}
void insert(int rt, int l, int r, int L, int R, int x, int o) {
	if(!rt) return;
	if(L <= l && r <= R) {
		if(o == 1) add(x, rt, 0);
		else add(rt, x, 0);
		return;
	}
	int mid = (l + r) >> 1;
	if(L <= mid) insert(ch[rt][0], l, mid, L, R, x, o);
	if(R > mid) insert(ch[rt][1], mid + 1, r, L, R, x, o);
}
queue<int> q0, q1;
void bfs() {
	memset(dis, 0x3f, sizeof dis);
	dis[id[cap]] = 0; vis[id[cap]] = 1;
	q0.push(id[cap]);
	while(q0.size() || q1.size()) {
		int u = 0;
		if(q0.size()) u = q0.front(), q0.pop();
		else u = q1.front(), q1.pop();
		for(int i = p[u]; i + 1; i = e[i].nxt) {
			int v = e[i].v, c = e[i].c;
			if(dis[u] + c < dis[v]) {
				dis[v] = dis[u] + c;
				if(!vis[v]) {
					vis[v] = 1;
					if(c) q1.push(v);
					else q0.push(v);
				} 
			}
		}
	}
}
int main() {
	init();
	scanf("%d%d%d", &n, &m, &cap);
	int rt1 = 0, rt2 = 0;
	build(rt1, rt2, 1, n);
	for(int i = 1; i <= m; i ++) {
		int l, r, ll, rr;
		scanf("%d%d%d%d", &l, &r, &ll, &rr);
		int fr = ++ tot, to = ++ tot;
		add(fr, to, 1);
		insert(rt2, 1, n, l, r, fr, 0);
		insert(rt1, 1, n, ll, rr, to, 1);
		fr = ++ tot, to = ++ tot;//一定要写
		add(fr, to, 1);
		insert(rt2, 1, n, ll, rr, fr, 0);
		insert(rt1, 1, n, l, r, to, 1);
	}
	bfs();
	for(int i = 1; i <= n; i ++) printf("%d\n", dis[id[i]]);
	return 0;
}
posted @ 2020-10-26 07:53  lahlah  阅读(38)  评论(0编辑  收藏  举报