这题不错,是一个最短路,但是中间有一个限制条件,就是等待时间
首先先看一下为什么仍然满足最短路
因为最短路肯定是每个结点求出最早到达的时间,那么其实不管有没等待,从队头取出去转移的肯定是最早的时间,仍然满足转移
那么就是等待时间如何去计算的问题
其实就先写一个函数,获得当前的颜色,和到下一个颜色的时间
然后如果颜色相同就不用等
如果颜色不同,到下一个颜色时间又不同,就返回其中小的时间
如果扔相同,就可以往后找4次(因为最多3次就进入循环节了),直到有一个时间不同,否则就是无限交替,这条路永远不能走
代码:
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
using namespace std;
const int N = 305;
const int M = 30005;
const int INF = 0x3f3f3f3f;
int s, t;
int n, m;
struct Node {
int tp, c, r, t;
void read(int tp) {
this->tp = tp;
scanf("%d%d%d", &c, &r, &t);
}
} node[N];
struct Edge {
int u, v, w;
Edge() {}
Edge(int u, int v, int w) {
this->u = u;
this->v = v;
this->w = w;
}
} edge[M];
int head[N], nxt[M], en;
void add_edge(int u, int v, int w) {
edge[en] = Edge(u, v, w);
nxt[en] = head[u];
head[u] = en++;
}
int d[N], vis[N], p[N];
struct State {
int u, w;
State() {}
State(int u, int w) {
this->u = u;
this->w = w;
}
bool operator < (const State &c) const {
return w > c.w;
}
};
void print(int u) {
if (u == s) {
printf("%d", u);
return;
}
print(p[u]);
printf(" %d", u);
}
void get(int now, Node u, int &ca, int &ta) {
int c = u.c, r = u.r, t = u.t, tp = u.tp;
if (now < c) {
ca = tp;
ta = c - now;
return;
}
now -= c; tp = !tp;
now %= (r + t);
if (tp == 0) {
if (now < r) {
ca = tp;
ta = r - now;
return;
}
now -= r; tp = !tp;
ca = tp;
ta = t - now;
return;
} else {
if (now < t) {
ca = tp;
ta = t - now;
return;
}
now -= t; tp = !tp;
ca = tp;
ta = r - now;
return;
}
}
int cal(int now, int u, int v) {
int ca, ta, cb, tb;
get(now, node[u], ca, ta);
get(now, node[v], cb, tb);
if (ca == cb) return 0;
if (ta != tb)
return min(ta, tb);
else {
int ans = 0;
int flag = 1;
for (int i = 0; i < 4; i++) {
ca = !ca;
cb = !cb;
ans += ta;
if (ca == 0) ta = node[u].r;
else ta = node[u].t;
if (cb == 0) tb = node[v].r;
else tb = node[v].t;
if (ta != tb) {
flag = 0;
break;
}
}
if (flag) return INF;
return ans + min(ta, tb);
}
}
void solve() {
for (int i = 1; i <= n; i++) d[i] = INF;
memset(vis, 0, sizeof(vis));
priority_queue<State> Q;
Q.push(State(s, 0));
d[s] = 0;
while (!Q.empty()) {
State x = Q.top();
int u = x.u;
if (u == t) break;
Q.pop();
if (vis[u]) continue;
vis[u] = 1;
for (int i = head[u]; i + 1; i = nxt[i]) {
int v = edge[i].v;
int w = edge[i].w;
int tmp = cal(x.w, u, v) + x.w + w;
if (d[v] > tmp) {
d[v] = tmp;
p[v] = u;
Q.push(State(v, d[v]));
}
}
}
if (d[t] == INF) printf("0\n");
else {
printf("%d\n", d[t]);
print(t);
printf("\n");
}
}
int main() {
while (~scanf("%d%d", &s, &t)) {
en = 0;
memset(head, -1, sizeof(head));
scanf("%d%d", &n, &m);
char s[2];
for (int i = 1; i <= n; i++) {
scanf("%s", s);
node[i].read(s[0] == 'P');
}
int u, v, w;
while (m--) {
scanf("%d%d%d", &u, &v, &w);
add_edge(u, v, w);
add_edge(v, u, w);
}
solve();
}
return 0;
}