P4568 [JLOI2011] 飞行路线

分层图算法

将图分为 \(k\) 层,层之间连权值为 \(0\) 的边,跑一遍 dij 就好了。目前已近学会了基本分层图建法,anguei的偏dp思维还需要掌握。

类似的题目还有 P4822 [BJWC2012]冻结

image

#include <bits/stdc++.h>

using namespace std;
int n, m, k;
const int maxn = 200005;
struct edges{
	int to, w;
};
// n 10^4, m 5* 10^4
vector<edges>e[maxn]; // k * n的范围
priority_queue<pair<int, int> > q;
bitset<maxn>vis;
int dis[maxn];
void dj(int start)
{
	memset(dis, 0x3f, sizeof(dis));
	dis[start] = 0;
	q.push(make_pair(-dis[start], start));
	while (q.size()) {
		int u = q.top().second; q.pop();
		if (vis[u]) continue;
		vis[u] = true;
		for (edges ed : e[u]) {
			int v = ed.to, w = ed.w;
			if (dis[v] > dis[u] + w) {
				dis[v] = dis[u] + w;
				q.push(make_pair(-dis[v], v));
			}
		}
	}
}
int main()
{
	int s, t;
	scanf("%d%d%d", &n, &m, &k);
	scanf("%d%d", &s, &t);
	for (int i = 1, _, __, ___; i <= m; i++) {
		scanf("%d%d%d", &_, &__, &___);
		e[_].push_back({__, ___});
		e[__].push_back({_, ___});
		// construct layered graph
		for (int layer = 1; layer <= k; layer++) {
			// ed in layer
			e[_ + layer * n].push_back({__ + layer * n, ___});
			e[__ + layer * n].push_back({_ + layer * n, ___});
			// ed between layers
			e[_ + (layer - 1) * n].push_back({__ + layer * n, 0});
			e[__ + (layer - 1) * n].push_back({_ + layer * n, 0});
		}
	}
	for (int i = 1; i <= k; i++) {
		e[t + (i - 1) * n].push_back({t + i * n, 0});
	}
	dj(s);
	printf("%d\n", dis[t + k * n]);
	return 0;
}
posted @ 2023-01-24 22:58  Vegdie  阅读(32)  评论(0编辑  收藏  举报