洛谷P1186 CodeVS1021 玛丽卡

Description:

麦克找了个新女朋友,玛丽卡对他非常恼火并伺机报复。

因为她和他们不住在同一个城市,因此她开始准备她的长途旅行。

在这个国家中每两个城市之间最多只有一条路相通,并且我们知道从一个城市到另一个城市路上所需花费的时间。

麦克在车中无意中听到有一条路正在维修,并且那儿正堵车,但没听清楚到底是哪一条路。无论哪一条路正在维修,从玛丽卡所在的城市都能到达麦克所在的城市。

玛丽卡将只从不堵车的路上通过,并且她将按最短路线行车。麦克希望知道在最糟糕的情况下玛丽卡到达他所在的城市需要多长时间,这样他就能保证他的女朋友离开该城市足够远。

编写程序,帮助麦克找出玛丽卡按最短路线通过不堵车道路到达他所在城市所需的最长时间(用分钟表示)。

Input:

第一行有两个用空格隔开的数N和M,分别表示城市的数量以及城市间道路的数量。1≤N≤1000,1≤M≤N*(N-1)/2。城市用数字1至N标识,麦克在城市1中,玛丽卡在城市N中。

接下来的M行中每行包含三个用空格隔开的数A,B和V。其中1≤A,B≤N,1≤V≤1000。这些数字表示在A和城市B中间有一条双行道,并且在V分钟内是就能通过。

Output:

输出文件的第一行中写出用分钟表示的最长时间,在这段时间中,无论哪条路在堵车,玛丽卡应该能够到达麦克处,如果少于这个时间的话,则必定存在一条路,该条路一旦堵车,玛丽卡就不能够赶到麦克处。

Sample Input:
5 7
1 2 8
1 4 10
2 3 9
2 4 10
2 5 1
3 4 7
3 5 10
 
Sample Output:
27

首先跑一遍最短路,维护路径,然后枚举最短路上的断边;

细节见代码:

 1 //P1186 玛丽卡
 2 /*
 3 SPFA最短路+枚举短边(在最短路上) 
 4 */
 5 #include<iostream> 
 6 #include<cstdio>
 7 #include<cstring>
 8 #include<queue>
 9 using namespace std;
10 
11 const int maxn = 1000 + 5;
12 const int maxm = 500000 + 5;
13 struct Edge {
14     int f, t, v;
15 }gra[maxm << 1];
16 int n, m, u, ans;
17 int fir[maxn], nxt[maxm << 1], dis[maxn], path[maxn];
18 bool used[maxn];
19 queue<int>Q;
20 void Build(int, int, int), SPFA(bool);
21 
22 int main()
23 {
24     memset(fir, -1, sizeof(fir));
25     scanf("%d%d", &n, &m);
26     for(int i = 0; i < m; i++) {
27         int f, t, v;
28         scanf("%d%d%d", &f, &t, &v);
29         Build(f, t, v);
30     }
31     SPFA(1);
32     path[1] = -1;//如果是i == 0的时候跳出,可能会从奇怪的地方结束; 
33     for(int i = path[n]; ~i; i = path[gra[i].f]) {
34         int tmp = gra[i].v;
35         gra[i].v = 1e9 + 7;
36         SPFA(0);
37         ans = max(ans, dis[n]);
38         gra[i].v = tmp;//恢复断边 
39     }
40     printf("%d
", ans);
41     return 0;
42 }
43 
44 void SPFA(bool f)
45 {
46     memset(dis, 0x7f, sizeof(dis));
47     dis[1] = 0;
48     Q.push(1);
49     while(!Q.empty()) {
50         int k = Q.front();
51         used[k] = 0;
52         Q.pop();
53         for(int i = fir[k]; ~i; i = nxt[i]) {
54             int tmp = gra[i].t;
55             if(dis[tmp] > dis[k] + gra[i].v) {
56                 dis[tmp] = dis[k] + gra[i].v;
57                 if(f) path[tmp] = i;//注意不要把之前的路径覆盖; 
58                 if(used[tmp]) continue;
59                 used[tmp] = 1;
60                 Q.push(tmp);
61             }
62         }
63     }
64 }
65 
66 void Build(int f, int t, int v)
67 {
68     gra[++u] = (Edge){f, t, v};
69     nxt[u] = fir[f], fir[f] = u;
70     gra[++u] = (Edge){t, f, v};
71     nxt[u] = fir[t], fir[t] = u;
72 }
原文地址:https://www.cnblogs.com/DreifxP/p/7752932.html