hdu 1595 find the longest of the shortest (dijkstra + spfa)
2015-09-15 16:57
573 查看
find the longest of the shortest
题目链接:Problem - 1595题目大意:现有一个无向图,其中某一条边不存在(要删除),求所有情况中最短路里的最大值。
题目分析:
思路一:枚举m条边,一一删除进行spfa求出最短路,然后比较出最大值。(超时)
思路二:先利用dijkstra求出最短路,再在最短路里枚举个边,一一删除进行spfa求出最短路,然后比较最大值。(AC)
思路分析:之所以能在最短路里删边求最小值,避免了一一枚举m条边,是因为删边后最短路要保持其值小,如果删除最短路意外的边,所有最小值都等于最短路的值,就不存在最大值了,所以利用原来最短路的基础上删边是优化的正确选择。
步骤: 1)存图 vector
2)找最短路 dijkstra
3)路径还原 (前驱)
4)在最短路中一一删边,每次求出最短路,比较出最大值(spfa)
贴AC代码:
#include <stdio.h> //定义输入/输出函数 #include <limits.h> //定义各种数据类型最值常量 #include <math.h> //定义数学函数 #include <stdlib.h> //定义杂项函数及内存分配函数 #include <string.h> //字符串处理 #include <algorithm>//算法 #include <queue>//队列 #include <stack>//栈 #include <vector> using namespace std; int n, m; int vis[1005]; int road[1005]; //记录路径 int a, b, t, couts, _a, _b, k; unsigned int ans, maxs; struct qq{ int to, cost; }; qq input; vector <qq> v[1005]; //存图 struct node{ int cost, pre; }; node low[1005]; //dijkstra用 struct pp{ int loc, cost; friend bool operator < (pp a, pp b) { return a.cost > b.cost; } }; //spfa优先队列用 void dijkstra() //求最短路径并还原路径 wa在此处3次 { for (int i = 1; i <= n; i++){ low[i].cost = 10000005; low[i].pre = 0; } memset(vis, 0, sizeof(vis)); low[1].cost = low[1].pre = 0; vis[1] = 1; for (int i = 0; i < v[1].size(); i++){ low[v[1][i].to].cost = v[1][i].cost; low[v[1][i].to].pre = 1; } for (int j = 1; j < n; j++){ unsigned int mins = -1; int loc = 1; for (int i = 1; i <= n; i++){ if (low[i].cost && low[i].cost < mins && vis[i] == 0){ mins = low[i].cost; loc = i; } } //找到最小值位置 vis[loc] = 1; for (int i = 0; i < v[loc].size(); i++){ if (vis[v[loc][i].to] == 1) continue; // 如果满足更新后的距离小于原来的值,则可以更新,并更新前驱 if (low[v[loc][i].to].cost > low[loc].cost + v[loc][i].cost){ low[v[loc][i].to].cost = low[loc].cost + v[loc][i].cost; low[v[loc][i].to].pre = loc; } } } //路径还原 k = n; couts = 0; road[couts++] = k; while(k != 0){ road[couts++] = low[k].pre; k = low[k].pre; } } void spfa() //求最短路的spfa 被题目绕进去了一开始求了最大值,wa了一次 { priority_queue <pp> q; while (!q.empty()) q.pop(); memset(vis, 0, sizeof(vis)); pp start; start.loc = 1; start.cost = 0; q.push(start); while (!q.empty()){ pp news, tmp; tmp = q.top(); q.pop(); vis[tmp.loc] += 1; if (tmp.loc == n){ if (ans > tmp.cost) ans = tmp.cost; break; } //要求出每次删边的最短路! for (int i = 0; i < v[tmp.loc].size(); i++){ news = tmp; if (vis[v[tmp.loc][i].to] == 1) continue; if (vis[tmp.loc] > 1) continue; //删边 if (tmp.loc == _a && v[tmp.loc][i].to == _b) continue; if (v[tmp.loc][i].to == _a && tmp.loc == _b) continue; news.loc = v[tmp.loc][i].to; news.cost += v[tmp.loc][i].cost; //printf("%d -> %d , cost %d\n", tmp.loc, news.loc, news.cost); q.push(news); } } } int main() { while (scanf("%d", &n) != EOF && n){ scanf("%d", &m); for (int i = 0; i < 1005; i++) v[i].clear(); for (int i = 0; i < m; i++){ scanf("%d%d%d", &a, &b, &t); input.to = b; input.cost = t; v[a].push_back(input); input.to = a; v[b].push_back(input); } dijkstra(); maxs = 0; for (int i = 0; i < couts - 1; i++){ //printf(" -> %d ", road[i]); _a = road[i]; _b = road[i+1]; ans = -1; spfa(); if (maxs < ans) maxs = ans; //在每次求出的最短路中找出最大值 } printf("%d\n", maxs); } }
相关文章推荐
- javaWeb中文乱码 解决方法
- IOS开发中图片资源使用png还是jpg格式
- C++读取windows系统性能技术器(PDH)
- 如何获取当前执行Assembly的位置
- 通过camera控制闪光灯
- jquery 设置select 默认值
- C语言之内存四区1
- laravel yii 区别 symfony route 参数
- 15个实用的Linux find命令示例
- java求树根
- AngularJS中页面间传值
- 2015个人项目(修改除法要求)
- Java HashMap、LinkedHashMap
- Java中一个对象的实例化过程
- 15_09_15 ( NullPointerException ) 空指针异常
- nginx配置详细说明
- fileoper.py
- Python Paramiko模块安装和使用
- 地图的相关使用(定位,地理编码,导航)
- zrclistview