Comet OJ - Contest #12 C - Bus Station

题意:

有 m 个公交车站,共开通了 n 1 + n 2 n_1 + n_2 趟公交,前 n 1 n_1 趟公交从 1 号一直开到 n 号,后 n 2 n_2 趟公交从 n 号一直开到 1 号,记 x i , j x_{i, j} 为第 j 趟公交抵达第 i 号车站的时间,假设公交车停靠时间极短。现在 t1 时刻你在第 s 号车站,在 t2 时刻会等到朋友,期间你希望尽可能在公交车上坐着,当然,最后要在 t2 时刻前回来 s 号车站,问等候朋友期间不在公交车上的可能的最少时间。( m ( n 1 + n 2 ) < = 1 e 6 , t 1 , t 2 , x i , j < = 1 e 9 m * (n_1 + n_2) <= 1e6, t_1, t_2, x_{i, j} <= 1e9 )

链接:

https://cometoj.com/contest/71/problem/C?problem_id=4018

解题思路:

这一看就很最短路。 考虑如何建图,显然每趟公交在每个车站最多被搭乘一次,因此可以 <公交编号,车站编号> 建点。对于每一趟公交,按行驶方向连权为 0 的有向边;对于同一车站停靠的不同公交,按时间升序连权为等待时间的有向边(注意存在不同公交在同一时刻停靠,此时它们之间应当连无向边)。最后,起点终点分别连上可搭乘的公交,跑最短路即可。

参考代码:

#include<bits/stdc++.h>

using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
#define pb push_back
#define sz(a) ((int)a.size())
#define mem(a, b) memset(a, b, sizeof a)
#define lson (rt << 1)
#define rson (rt << 1 | 1)
#define gmid (l + r >> 1)
const int maxn = 1e6 + 5;
const int maxm = 1e6 + 5;
const int mod = 1e9 + 7;
//const int inf = 0x3f3f3f3f;

const ll inf = 0x3f3f3f3f3f3f3f3f;
typedef pair<ll, int> pli;
priority_queue<pli, vector<pli>, greater<pli> > q;
vector<pli> G[maxn];
vector<pii> wi[maxn];
ll dis[maxn];
int m, n1, n2, sp, tp, t1, t2, n;

inline int getId(int x, int y){

	return (x - 1) * (n1 + n2) + y;
}

inline int check(int t){

	return t >= t1 && t <= t2;
}

void build(){

	for(int i = 1; i < m; ++i){

		for(int j = 1; j <= n1; ++j){

			int u = wi[i][j].second, v = wi[i + 1][j].second;
			if(check(wi[i][j].first) && check(wi[i + 1][j].first)) G[u].pb({0, v});
		}
	}
	for(int i = 2; i <= m; ++i){

		for(int j = n1 + 1; j <= n; ++j){

			int u = wi[i][j].second, v = wi[i - 1][j].second;
			if(check(wi[i][j].first) && check(wi[i - 1][j].first)) G[u].pb({0, v});
		}
	}
	for(int i = 1; i <= m; ++i) sort(wi[i].begin(), wi[i].end());
	for(int i = 1; i <= m; ++i){

		for(int j = 1; j < n; ++j){

			int u = wi[i][j].second, v = wi[i][j + 1].second;
			int t1 = wi[i][j].first, t2 = wi[i][j + 1].first;
			if(!check(t1) || !check(t2)) continue;
			G[u].pb({t2 - t1, v});
			if(t1 == t2) G[v].pb({0, u});
		}
	}
	for(int i = 1; i < sz(wi[sp]); ++i){

		int u = wi[sp][i].second, t = wi[sp][i].first;
		if(check(t)) G[0].pb({t - t1, u}), G[u].pb({t2 - t, tp});
	}
	G[0].pb({t2 - t1, tp});
}

void dij(int s){

	for(int i = 0; i <= tp; ++i) dis[i] = inf;
	dis[s] = 0, q.push({dis[s], s});
	while(!q.empty()){

		int u = q.top().second; ll d = q.top().first; q.pop();
		if(d != dis[u]) continue;
		for(int i = 0; i < sz(G[u]); ++i){

			int v = G[u][i].second, w = G[u][i].first;
			if(dis[v] > dis[u] + w){

				dis[v] = dis[u] + w;
				q.push({dis[v], v});
			}
		}
	}
}

const int maxs = 1e3 + 5;
char buf[maxs], *p1 = buf, *p2 = buf;
inline char fr(){

	return p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, maxs, stdin)) == p1 ? -1 : *p1++;
}
#define gc fr()
inline void read(int &x){

	char ch; while(!isdigit(ch = gc)); x = ch ^ 48;
	while(isdigit(ch = gc)) x = x * 10 + (ch ^ 48);
}

int main(){

//	ios::sync_with_stdio(0); cin.tie(0);
	int t; read(t);
	while(t--){

		read(m), read(n1), read(n2), read(sp), read(t1), read(t2);
		n = n1 + n2, tp = m * n + 1;
		for(int i = 1; i <= m; ++i){

			wi[i].pb({-1, -1});
			for(int j = 1; j <= n; ++j){

				int w; read(w);
				wi[i].pb({w, getId(i, j)});
			}
		}
		build(), dij(0);
		printf("%lld\n", dis[tp]);
		for(int i = 0; i <= tp; ++i) G[i].clear();
		for(int i = 1; i <= m; ++i) wi[i].clear();
	}
    return 0;
}
发布了55 篇原创文章 · 获赞 0 · 访问量 1259

猜你喜欢

转载自blog.csdn.net/weixin_44059127/article/details/102527941