Codevs 1021 玛丽卡
2015-08-26 13:03
337 查看
Codevs 1021 玛丽卡
题目地址:http://codevs.cn/problem/1021/题目描述 Description
麦克找了个新女朋友,玛丽卡对他非常恼火并伺机报复。因为她和他们不住在同一个城市,因此她开始准备她的长途旅行。
在这个国家中每两个城市之间最多只有一条路相通,并且我们知道从一个城市到另一个城市路上所需花费的时间。
麦克在车中无意中听到有一条路正在维修,并且那儿正堵车,但没听清楚到底是哪一条路。无论哪一条路正在维修,从玛丽卡所在的城市都能到达麦克所在的城市。
玛丽卡将只从不堵车的路上通过,并且她将按最短路线行车。麦克希望知道在最糟糕的情况下玛丽卡到达他所在的城市需要多长时间,这样他就能保证他的女朋友离开该城市足够远编写程序,帮助麦克找出玛丽卡按最短路线通过不堵车道路到达他所在城市所需的最长时间(用分钟表示)。
输入描述 Input Description
第一行有两个用空格隔开的数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 Description
输出文件的第一行中写出用分钟表示的最长时间,在这段时间中,无论哪条路在堵车,玛丽卡应该能够到达麦克处,如果少于这个时间的话,则必定存在一条路,该条路一旦堵车,玛丽卡就不能够赶到麦克处。样例输入 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
这道题先跑一遍SPFA,找出 点1 到 点N 最短路的路径,然后枚举这条路径上的所有边,依次将它们的权值赋为 +∞ 然后跑一遍SPFA。答案就是 Max(disN) 了。
因为如果堵车那条路不在 点1 到 点N 最短路的路径 上时,最小时间应该就是 点1 到 点N 的距离。
#include <cstdio> #include <deque> #define INF 1000000007 int n, m; int hu[1005], hv[1005], f[1005]; bool vis[1005]; struct edge_type { int u, v, w, nu, nv; }; edge_type edge[1000005]; int dis[1005]; std::deque<int> q; int main() { int x, y, z; scanf("%d%d", &n, &m); for (int i = 1; i <= m; ++i) { scanf("%d%d%d", &x, &y, &z); edge[i].u = x; edge[i].v = y; edge[i].w = z; edge[i].nu = hu[x]; edge[i].nv = hv[y]; hu[x] = i; hv[y] = i; } int tmp, now, p, ans = 0, ttmp, ei; q.clear(); for (int i = 1; i <= n; ++i) dis[i] = INF; dis[1] = 0; f[1] = 0; vis[1] = true; q.push_back(1); while (!q.empty()) { now = q.front(); q.pop_front(); vis[now] = false; p = hu[now]; while (p) { if (dis[edge[p].v] > dis[now] + edge[p].w) { dis[edge[p].v] = dis[now] + edge[p].w; f[edge[p].v] = p; if (!vis[edge[p].v]) { q.push_back(edge[p].v); vis[edge[p].v] = true; } } p = edge[p].nu; } p = hv[now]; while (p) { if (dis[edge[p].u] > dis[now] + edge[p].w) { dis[edge[p].u] = dis[now] + edge[p].w; f[edge[p].u] = p; if (!vis[edge[p].u]) { q.push_back(edge[p].u); vis[edge[p].u] = true; } } p = edge[p].nv; } } ttmp = n; ei = f ; while(ei) { tmp = edge[ei].w; edge[ei].w = INF; q.clear(); for (int i = 1; i <= n; ++i) dis[i] = INF; dis[1] = 0; f[1] = 0; vis[1] = true; q.push_back(1); while (!q.empty()) { now = q.front(); q.pop_front(); vis[now] = false; p = hu[now]; while (p) { if (dis[edge[p].v] > dis[now] + edge[p].w) { dis[edge[p].v] = dis[now] + edge[p].w; f[edge[p].v] = p; if (!vis[edge[p].v]) { q.push_back(edge[p].v); vis[edge[p].v] = true; } } p = edge[p].nu; } p = hv[now]; while (p) { if (dis[edge[p].u] > dis[now] + edge[p].w) { dis[edge[p].u] = dis[now] + edge[p].w; f[edge[p].u] = p; if (!vis[edge[p].u]) { q.push_back(edge[p].u); vis[edge[p].u] = true; } } p = edge[p].nv; } } if (ans < dis ) ans = dis ; edge[ei].w = tmp; ttmp = edge[ei].u ^ edge[ei].v ^ ttmp; ei = f[ttmp]; } printf("%d", ans); }
相关文章推荐
- 使用C++实现JNI接口需要注意的事项
- 关于指针的一些事情
- c++ primer 第五版 笔记前言
- share_ptr的几个注意点
- Lua中调用C++函数示例
- Lua教程(一):在C++中嵌入Lua脚本
- Lua教程(二):C++和Lua相互传递数据示例
- C++联合体转换成C#结构的实现方法
- C++编写简单的打靶游戏
- C++ 自定义控件的移植问题
- C++变位词问题分析
- C/C++数据对齐详细解析
- C++基于栈实现铁轨问题
- C++中引用的使用总结
- 使用Lua来扩展C++程序的方法
- C++中调用Lua函数实例
- Lua和C++的通信流程代码实例
- C与C++之间相互调用实例方法讲解
- C++ Custom Control控件向父窗体发送对应的消息
- C++中拷贝构造函数的应用详解