题目链接:
https://cn.vjudge.net/problem/SGU-103#author=ECUST_FZL
题目大意:
Dingiville 城市的交通规则非常奇怪,城市公路通过路口相连,两个不同路口之间最多只有一条直达公路。公路的起止点不会是同一路口。在任意一条公路上顺不同方向走所需 时间相同。每一个路口都有交通灯,这些交通灯在某一时刻要么是蓝色,要么是紫色。同一个灯上2个颜色的维持时间受到定期调控,总是蓝色持续一段时间,紫色 持续一段时间。交通规则规定两个路口可以通车仅当公路两边交通灯的颜色相同(也就是说只要你在A城市看见A与B的交通灯颜色相同,那么你就可以走上A-B 这条路并到达B点)。交通工具可以在路口等候。现在你有这个城市的地图,包含:
• 通过所有公路需要的时间(整数)
• 每个路口交通灯两种颜色的持续时间(整数)
• 每个路口交通灯的初始颜色以及初始颜色的持续时间(整数).
你的任务是找到一条从起点到终点的最快路径,当有多条这样的路径存在时,你只需输出任意一条即可。
解题思路:
可以用SPFA求解最短路,只是松弛的时候,计算两点的路径的时候需要计算一下。
只有u点的颜色和v点的颜色是一致的时候才可以从u到v,可以写出一个函数计算某时刻某个点的颜色,对于u v路径,可以枚举在dis[u] - dis[u] + 300内的所有时间直到两点颜色相同。这是由于周期最多为200,在一个半周期内没有解的话就无解了。
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int INF = 0x3f3f3f3f; 4 const int maxn = 310; 5 struct Edge 6 { 7 int u, v, w; 8 Edge(){} 9 Edge(int u, int v, int w):u(u), v(v), w(w){} 10 }; 11 vector<Edge>edges;//存每一条边 12 vector<int>Map[maxn];//存i相连的边的下标 13 void addedge(int u, int v, int w) 14 { 15 edges.push_back(Edge(u, v, w)); 16 int m = edges.size(); 17 Map[u].push_back(m - 1); 18 edges.push_back(Edge(v, u, w)); 19 m = edges.size(); 20 Map[v].push_back(m - 1); 21 } 22 23 struct node 24 { 25 bool color;//color = 0为blue color = 1为purple 26 int init, tb, tp, tsum; 27 }a[maxn]; 28 29 int color(int u, int time)//计算time时候 u点的颜色 30 { 31 time = (time - a[u].init + a[u].tsum) % a[u].tsum; 32 if(a[u].color)return time < a[u].tb ? 0 : 1;//最初为紫色的时候 33 else return time < a[u].tp ? 1 : 0;//最初为蓝色的时候 34 } 35 int Time(int u, int v, int now)//返回从u到v可以开始走的时间 36 { 37 for(int i = now; i <= now + 300; i++) 38 if(color(u, i) == color(v, i))return i; 39 return INF; 40 } 41 42 bool vis[maxn]; 43 int d[maxn], path[maxn]; 44 int n, m; 45 int SPFA(int s, int t) 46 { 47 memset(vis, 0, sizeof(vis)); 48 memset(path, -1, sizeof(path)); 49 for(int i = 1; i <= n; i++)d[i] = INF; 50 d[s] = 0; 51 vis[s] = 1; 52 queue<int>q; 53 q.push(s); 54 while(!q.empty()) 55 { 56 int u = q.front(); 57 q.pop(); 58 vis[u] = 0; 59 for(int i = 0; i < Map[u].size(); i++) 60 { 61 Edge& e = edges[Map[u][i]]; 62 int v = e.v; 63 int w = Time(u, v, d[u]) + e.w;//这是u到v的时间 64 if(d[v] > w) 65 { 66 d[v] = w; 67 path[v] = Map[u][i]; 68 if(!vis[v]) 69 { 70 q.push(v); 71 vis[v] = 1; 72 } 73 } 74 75 } 76 } 77 return d[t]; 78 } 79 void Print(int s, int t) 80 { 81 stack<int>q; 82 int x = t; 83 while(path[x] != -1) 84 { 85 q.push(x); 86 x = edges[path[x]].u; 87 } 88 printf("%d", s); 89 while(!q.empty()) 90 { 91 printf(" %d", q.top()); 92 q.pop(); 93 } 94 puts(""); 95 } 96 int main() 97 { 98 int s, t; 99 char c[5]; 100 scanf("%d%d", &s, &t); 101 scanf("%d%d", &n, &m); 102 for(int i = 1; i <= n; i++) 103 { 104 scanf("%s%d%d%d", c, &a[i].init, &a[i].tb, &a[i].tp); 105 a[i].tsum = a[i].tb + a[i].tp; 106 a[i].color = c[0] == 'P'; 107 } 108 int u, v, w; 109 while(m--) 110 { 111 scanf("%d%d%d", &u, &v, &w); 112 addedge(u, v, w); 113 } 114 int ans = SPFA(s, t); 115 if(ans >= INF) 116 { 117 printf("0\n"); 118 } 119 else 120 { 121 printf("%d\n", ans); 122 Print(s, t); 123 } 124 return 0; 125 }