sgu 103 Traffic Lights
这道题难得不是算法,而是处理。
题意就是让你求最短路,只有当两个点在某一秒颜色相同时,这条边才可以通行,输入首先给你 起点和终点, 然后给你 点数和边数, 接下来 n 行 初始颜色,初始颜色持续时间,蓝色持续时间,紫色持续时间。 再接下来m行,无向边的起点和终点以及通过所需的时间。
题意他说的有些模糊,样例我看了很多遍也不对,后来才发现如果你在某一秒到达一个点,这一秒颜色和下一个点相同,但是下一秒这个点就要变色,那么是不能在这一秒走的,这个具体处理起来很麻烦
这篇博客说的很详细,戳链接:http://www.cnblogs.com/Rinyo/archive/2012/11/29/2795030.html
上代码……
#include <cstdio> #include <cstring> #include <iostream> #include <cstdlib> #include <algorithm> #include <cmath> #include <queue> #define N 350 #define M 15000*2 #define inf 1<<30 using namespace std; int n, m, S, T; int p[N] = {0}, next[M], v[M], bnum = 0, c[M], fa[N]; int dis[N], vis[N], firstcolor[N], firstremain[N], remain[N][2]; void addbian(int x, int y, int z) { bnum++; next[bnum] = p[x]; p[x] = bnum; v[bnum] = y; c[bnum] = z; bnum++; next[bnum] = p[y]; p[y] = bnum; v[bnum] = x; c[bnum] = z; } void calt(int now, int nowtime, int &color, int &changetime) { if (nowtime < firstremain[now]) { color = firstcolor[now]; changetime = firstremain[now]; return; } int k; k = (nowtime-firstremain[now]) % (remain[now][0]+remain[now][1]); nowtime -= k; if (firstcolor[now]) { if (k < remain[now][0]) { color = 0; changetime = nowtime + remain[now][0]; } else { color = 1; changetime = nowtime + remain[now][1] + remain[now][0]; } } else { if (k < remain[now][1]) { color = 1; changetime = nowtime + remain[now][1]; } else { color = 0; changetime = nowtime + remain[now][0] + remain[now][1]; } } } int gettime(int x, int y, int nowtime, int dis, int f) { int ca, cb, ta, tb, ta1, ca1; calt(x, nowtime, ca, ta); calt(y, nowtime, cb, tb); if (ca == cb) return nowtime + dis; if (ta == tb) { if (f == 0) return gettime(x, y, ta, dis, f+1); else if (nowtime <= firstremain[x] || nowtime <= firstremain[y]) gettime(x, y, ta, dis, f+1); else return inf; } return min(ta, tb) + dis; } void spfa() { queue<int> q; for (int i = 1; i <= n; ++i) { vis[i] = 0; dis[i] = inf; } q.push(S); dis[S] = 0; vis[S] = 1; while (!q.empty()) { int now = q.front(); q.pop(); int k = p[now]; while (k != 0) { int t = gettime(now, v[k], dis[now], c[k], 0); if (dis[v[k]] > t) { dis[v[k]] = t; fa[v[k]] = now; if (!vis[v[k]]) { vis[v[k]] = 1; q.push(v[k]); } } k = next[k]; } vis[now] = 0; } } void print(int now) { if (now == S) printf("%d ", S); else { print(fa[now]); if (now != T) printf("%d ", now); else printf("%d\n", T); } } int main() { scanf("%d%d", &S, &T); scanf("%d%d", &n, &m); for (int i = 1; i <= n; ++i) { char s[2]; scanf("%s", s); if (s[0] == 'B') firstcolor[i] = 0; else firstcolor[i] = 1; scanf("%d%d%d", &firstremain[i], &remain[i][0], &remain[i][1]); } for (int i = 1; i <= m; ++i) { int x, y, z; scanf("%d%d%d", &x, &y, &z); addbian(x, y, z); } spfa(); if (dis[T] == inf) { printf("0\n"); return 0; } printf("%d\n", dis[T]); print(T); }