您的位置:首页 > 其它

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);
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: