【牛客小白月赛16 】J. 小雨坐地铁

题意:
\(n\)个站点,\(m\)条地铁线,每条线经过的站点个数为\(c\)个,坐\(i\)号线需要花费\(a_i\)的价格,在第\(i\)号线上每坐一站就要花费\(b_i\)的价格,如果同一站有多条地铁线路,那么可以同站换乘。
现在问从\(s \rightarrow t\)的最小花费是多少。

思路:
可以建一个\(m\)层的最短路,第\(i\)层表示第\(i\)号线的连通状态。
然后根据同站换乘,层与层之间连边,但是这样边数就是\(O(nm^2)\)的。
我们考虑对于每个站建立一个虚点,从地铁线中的点到虚点的代价为\(0\),从虚点到地铁线中的代价为那条地铁线的\(a_i\),然后就把图的规模缩小成了\(O(nm)\)了。

代码:

#include <bits/stdc++.h>
using namespace std;

#define ll long long
#define INFLL 0x3f3f3f3f3f3f3f3f
#define N 1000010
int n, m, s, t;
struct Graph {
	struct node {
		int to, nx, w;
		node() {}
		node (int to, int nx, int w) : to(to), nx(nx), w(w) {}
	}a[N << 1];
	int head[N], pos;
	void init() {
		memset(head, -1, sizeof head);
		pos = 0;
	}
	void add(int u, int v, int w) {
		a[pos] = node(v, head[u], w); head[u] = pos++;
	}
}G;
#define erp(u) for (int it = G.head[u], v = G.a[it].to, w = G.a[it].w; ~it; it = G.a[it].nx, v = G.a[it].to, w = G.a[it].w)

struct node {
	int u; ll w;
	node() {}
	node(int u, ll w) : u(u), w(w) {}
	bool operator < (const node &other) const {
		return w > other.w;
	}
};

ll dist[N]; bool used[N];
void Dijkstra(int s) {
	memset(dist, 0x3f, sizeof dist);
	memset(used, 0, sizeof used);
	priority_queue <node> pq;
	dist[s] = 0;
	pq.push(node(s, 0));
	while (!pq.empty()) {
		int u = pq.top().u; pq.pop();
		if (used[u]) continue;
		used[u] = 1;
		erp(u) if (dist[v] > dist[u] + w) {
			dist[v] = dist[u] + w;
			pq.push(node(v, dist[v]));
		}
	}
}


int main() {
	while (scanf("%d%d%d%d", &n, &m, &s, &t) != EOF) {
		G.init();
		for (int i = 1, a, b, c, u, v; i <= m; ++i) {
			scanf("%d%d%d", &a, &b, &c);
			for (int j = 1; j <= c; ++j) {
				scanf("%d", &v);
				if (j > 1) {
					G.add((i - 1) * n + u, (i - 1) * n + v, b);
					G.add((i - 1) * n + v, (i - 1) * n + u, b);	
				}
				G.add((i - 1) * n + v, m * n + v, 0);
				G.add(m * n + v, (i - 1) * n + v, a);
				u = v;
			}
		}
		Dijkstra(m * n + s);
		ll res = dist[m * n + t];
		if (res == INFLL) res = -1;
		printf("%lld\n", res);
	}
	return 0;
}


posted @ 2019-07-14 07:17  Dup4  阅读(213)  评论(0)    收藏  举报