hdu 1595 find the longest of the shortest (dijkstra + spfa)

来源:互联网 发布:java 什么是包 编辑:程序博客网 时间:2024/05/22 13:38


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);    }}


0 0
原创粉丝点击