SGU---103 最短路变形

题目链接:

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 }

 

posted @ 2018-06-02 20:57  _努力努力再努力x  阅读(261)  评论(0编辑  收藏  举报