翻译:
Dingiville 城市的交通规则非常奇怪,城市公路通过路口相连,两个不同路口之间最多只有一条直达公路。公路的起止点不会是同一路口。
在任意一条公路上顺不同方向走所需时间相同。
每一个路口都有交通灯,这些交通灯在某一时刻要么是蓝色,要么是紫色。
同一个灯上2个颜色的维持时间受到定期调控,总是蓝色持续一段时间,紫色持续一段时间。
交通规则规定两个路口可以通车仅当公路两边交通灯的颜色相同(也就是说只要你在A城市看见A与B的交通灯颜色相同,那么你就可以走上A-B 这条路并到达B点)。
交通工具可以在路口等候。现在你有这个城市的地图,包含:
1 通过所有公路需要的时间(整数)
2 每个路口交通灯两种颜色的持续时间(整数)
3 每个路口交通灯的初始颜色以及初始颜色的持续时间(整数).
你的任务是找到一条从起点到终点的最快路径,当有多条这样的路径存在时,你只需输出任意一条即可。
分析:
最短路
#include <cstdio>
#include <cstring>
#include <cmath>
using namespace std;
#define inc(x) (x = (x+1) % MOD)
const int maxn = 306;
const int maxm = 28006;
const int MOD = maxm;
const int oo = 0x3f3f3f3f;
inline int read()
{
int x = 0, f = 1, t = getchar();
while(t < '0' || t > '9') {
if(t == '-') f = -1;
t = getchar();
}
while(t >= '0' && t <= '9') {
x = (x << 1) + (x << 3) + t - '0';
t = getchar();
}
return x * f;
}
inline int min(int a, int b) { return a < b ? a : b; }
struct Edge
{
int u, v, w;
Edge(int u = 0, int v = 0, int w = 0): u(u), v(v), w(w) {}
};
int n, m, s, t;
int C[maxn], R[maxn], T[maxn][2], S[maxn];
int head[maxn];
int next[maxm];
Edge edge[maxm];
int fa[maxn];
void addedge(int a, int b, int c)
{
edge[++m] = Edge(a, b, c);
next[m] = head[a], head[a] = m;
}
void init()
{
memset(head, -1, sizeof(head));
s = read(), t = read(), n = read();
int mm = read(), a, b, c;
for(int i = 1; i <= n; ++i) {
C[i] = (getchar() == 'B' ? 0 : 1);
R[i] = read(), T[i][0] = read(), T[i][1] = read();
S[i] = T[i][0] + T[i][1];
}
for(int i = 1; i <= mm; ++i) {
a = read(), b = read(), c = read();
addedge(a, b, c);
addedge(b, a, c);
}
}
int color(int u, int t, int &r)
{
if(t < R[u]) {
r = R[u] - t;
return C[u];
}
t = (t - R[u]) % S[u];
if(t >= T[u][C[u]^1]) {
r = S[u] - t;
return C[u];
}
else {
r = T[u][C[u]^1] - t;
return C[u]^1;
}
}
int calc(int u, int v, int t)
{
int ru, rv, cu = color(u, t, ru), cv = color(v, t, rv);
if(cu == cv) return 0;
if(ru != rv) return min(ru, rv);
if(T[u][!cu] != T[v][!cv])
return ru + min(T[u][!cu], T[v][!cv]);
return oo;
}
int spfa()
{
static int que[maxm] = {s}, h = 0, r = 1;
static int dis[maxn], inq[maxn] = {0};
memset(dis, oo, sizeof(dis)), dis[s] = 0;
while(h != r) {
int x = que[h];
inc(h);
inq[x] = 0;
for(int i = head[x]; i != -1; i = next[i]) {
Edge &e = edge[i];
int cost = calc(x, e.v, dis[x]);
if(cost == oo) continue;
if(dis[e.v] > dis[x] + e.w + cost) {
dis[e.v] = dis[x] + e.w + cost;
fa[e.v] = x;
if(!inq[e.v]) {
que[r] = e.v;
inq[e.v] = 1;
inc(r);
}
}
}
}
return dis[t];
}
void work()
{
static int stack[maxn] = {0}, top = 0;
int ans = spfa();
if(ans < oo) {
printf("%d\n", ans);
for(int x = t; x != s; x = fa[x])
stack[top++] = x;
printf("%d", s);
while(top--) printf(" %d", stack[top]);
}
else puts("0");
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("input.txt", "r", stdin);
freopen("output.txt", "w", stdout);
#endif
init();
work();
#ifndef ONLINE_JUDGE
fclose(stdin);
fclose(stdout);
#endif
return 0;
}