#include <cstdio>
#include <iostream>
#include <cmath>
#include <cstring>
#include <queue>
using namespace std;
#define int long long
const int N = 405;
const int M = 28005 * 2;
int gcd(int x , int y) {
return (y == 0) ? x : gcd(y , x % y);
}
int lcm(int x , int y) {
return x * y / gcd(x , y);
}
struct Mod_holder {
int mod , l , r , Min;
void check(void) {
printf("%lld %lld %lld %lld\n" , mod , l , r , Min);
}
}col[N][2] , Ind , Tmp;
// mod holder
int fir[N] , ne[M] , to[M] , C[M] , cnt;
#define Foreachson(i , x) for(int i = fir[x];i;i = ne[i])
void add(int x , int y , int w) {
ne[++ cnt] = fir[x]; fir[x] = cnt; to[cnt] = y; C[cnt] = w;
}
void link(int x , int y , int w) {
add(x , y , w); add(y , x , w);
}
// Edge dancer
bool in (int now , Mod_holder xxx) {
now %= xxx.mod;
if(xxx.Min < 0) {
xxx.l += xxx.mod; xxx.r += xxx.mod;
if(now >= xxx.l && now <= xxx.r) return 1;
xxx.l -= xxx.mod; xxx.r -= xxx.mod;
}
// Åжϱ߽çҪעÒâ.
if(now >= xxx.l && now <= xxx.r) return 1;
return 0;
}
int Min_Time_get (Mod_holder a , Mod_holder b , int from , int time) {
from = max(from , max(a.Min , b.Min));
int all = from;
while(!in(from , a) || !in(from , b)) {
from ++;
if(from > lcm(a.mod , b.mod) * 2 + all) return -1;
}
return from;
}
// shortest path processor
struct Point {
int cur , time , pre;
friend bool operator < (Point xxx , Point yyy) {
return xxx.time > yyy.time;
}
}ind , tmp;
priority_queue <Point> q;
int s , t , dis[N] , pre[N];
bool vis[N];
void push(int cur , int time , int pre) {
tmp.cur = cur; tmp.time = time; tmp.pre = pre;
q.push(tmp);
}
void print(int x) {
if(x != s) print(pre[x]);
if(x == t) printf("%lld" , x);
if(x == t) return;
printf("%lld " , x);
}
void dijkstra(int s) {
while(!q.empty()) q.pop();
push(s , 0 , 0);
while(!q.empty()) {
while(!q.empty() && vis[q.top().cur]) q.pop();
if(q.empty()) break;
ind = q.top(); q.pop();
dis[ind.cur] = ind.time; pre[ind.cur] = ind.pre;vis[ind.cur] = 1;
Foreachson(i , ind.cur) {
int V = to[i];
if(vis[V]) continue;
int Min = 2e9;
for(int j = 0;j <= 1;j ++) {
Ind = col[ind.cur][j]; Tmp = col[V][j];
int now = Min_Time_get(Ind , Tmp , ind.time , 0);
if(now == -1) continue;
Min = min(Min , now);
}
Min += C[i];
if(Min > 2e8) continue;
push(V , Min , ind.cur);
}
}
if(vis[t]) {
printf("%lld\n" , dis[t]); print(t);
}
else puts("0");
}
int n , m;
void build(void) {
scanf("%lld%lld" , &s , &t);
scanf("%lld%lld" , &n , &m);
for(int i = 1;i <= n;i ++) {
char c = getchar(); int still , B , P;
while(c != 'P' && c != 'B') c = getchar();
scanf("%lld%lld%lld" , &still , &B , &P);
int ty = 0; if(c == 'P') ty = 1;
col[i][0].mod = col[i][1].mod = B + P;
if(ty == 0) {
col[i][0].Min = still - B + 1; col[i][0].l = still - B + 1; col[i][0].r = still;
col[i][1].Min = still + 1; col[i][1].l = still + 1; col[i][1].r = still + P;
}
else {
col[i][0].Min = still - P + 1; col[i][0].l = still - P + 1; col[i][0].r = still;
col[i][1].Min = still + 1; col[i][1].l = still + 1; col[i][1].r = still + B;
swap(col[i][0] , col[i][1]);
}
col[i][0].l --; col[i][0].r --; col[i][1].l --; col[i][1].r --; col[i][0].Min --; col[i][1].Min --;
}
for(int i = 1;i <= m;i ++) {
int x , y , w;
scanf("%lld%lld%lld" , &x , &y , &w);
link(x , y , w);
}
}
main(void) {
// freopen("data.txt" , "r" , stdin);
// freopen("myout.txt" , "w" , stdout);
build();
dijkstra(s);
return 0;
}
这题对问题边界的考虑要十分清晰, 难点在于找时间的下一个相遇点,这里我原本用了十分繁琐的方法,其实完全没有必要,直接狂扫就可以了,并且退出时的边界导致我调试了很久,这种地方一定要在打代码前注意,多分函数,要加强读题和信息转化能力.