线段树优化建图,求条
查看原帖
线段树优化建图,求条
481621
Zhang_Wenjie楼主2024/11/5 13:54

我是分三个点集:第一颗线段树是维护点到区间上,1 ~ 4n,第二颗线段树是区间到点,1 + 4n ~ n + 4n,最后是原图中的点 1 + 8n ~ n + 8n

#include <bits/stdc++.h>
#define re register int 
#define lp p << 1
#define rp p << 1 | 1
#define n4 4 * n
#define n8 8 * n

using namespace std;
typedef long long LL;
typedef pair<LL, int> PII;
const int N = 9e5 + 10, M = 2e6 + 10;
const LL inf = 1e18 + 10;

struct Edge
{
	int to, next;
	LL w;
}e[M];
int idx, h[N];
struct Tree
{
	int l, r;
}t[N];
int n, q, s;
LL dis[N];
bool st[N];

inline void add(int x, int y, LL w)
{
	++ idx;
	e[idx].to = y, e[idx].w = w, e[idx].next = h[x];
	h[x] = idx;
}

inline void build(int p, int l, int r)
{
	t[p].l = l, t[p].r = r;
	if (l == r)
	{
		add(p, l + n8, 0), add(l + n8, p, 0);
		add(p + n4, l + n8, 0), add(l + n8, p + n4, 0);
		return;
	}
	add(p, lp, 0), add(p, rp, 0);
	add(lp + n4, p + n4, 0), add(rp + n4, p + n4, 0);
	
	int mid = (l + r) >> 1;
	build(lp, l, mid); build(rp, mid + 1, r);
}

inline void update(int p, int l, int r, int u, LL w, int type)
{
	if (l <= t[p].l && t[p].r <= r)
	{
		if (type) add(p + n4, u + n8, w);
		else add(u + n8, p, w);
		return;
	}
	int mid = (t[p].l + t[p].r) >> 1;
	if (l <= mid) update(lp, l, r, u, w, type);
	if (r > mid) update(rp, l, r, u, w, type);
}

inline void dij()
{
	priority_queue<PII, vector<PII>, greater<PII> > q;
	for (re i = 1; i <= n + n8; i ++) dis[i] = inf;
	
	dis[s + n8] = 0;
	q.push({0, s + n8});
	while (!q.empty())
	{
		int x = q.top().second; q.pop();
		if (st[x]) continue;
		st[x] = true;
		
		for (re i = h[x]; i; i = e[i].next)
		{
			int y = e[i].to; LL w = e[i].w;
			if (dis[y] > dis[x] + w)
			{
				dis[y] = dis[x] + w;
				q.push({dis[y], y});
			}
		}
	}
}

int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0); cout.tie(0);
	
	cin >> n >> q >> s;
	build(1, 1, n);
	while (q --)
	{
		int op, u, v, l, r; LL w; 
		cin >> op;
		if (op == 1)
		{
			cin >> u >> v >> w;
			add(u + n8, v + n8, w);
		}
		if (op == 2) // u -> [l, r]
		{
			cin >> u >> l >> r >> w;
			update(1, l, r, u, w, 0);
		}
		if (op == 3) // [l, r] -> u
		{
			cin >> u >> l >> r >> w;
			update(1, l, r, u, w, 1);
		}
	}	
	dij();
	for (re i = 1; i <= n; i ++) cout << (dis[i + n8] == inf ? -1 : dis[i + n8]) << ' ';
	cout << '\n';
	
	return 0;
}

2024/11/5 13:54
加载中...