poj 3255 最短路和次短路

题意:

  • 求从起点到终点的次短路

Bellman-Ford算法:

  • 把有向图的边存起来,然后每次扫描所有边,来更新起点到每个点的最短路,当这一次扫描,一次更新都没有的时候,说明所有顶点的最短路已经求得。复杂度是 O(|E||V|) 。根据这个思想还可以来判断图中存不存在负圈。

Dijkstra算法(戴克斯特拉):

  • 1.初始所有顶点都是未使用过,且除了起点最短距离为0外,所有顶点最短距离都为INF。
  • 2.找出所有未使用顶点中,最短距离最小的点,由它更新出所有和它相连顶点的最短路。
  • 3.重复2步骤,直到所有顶点都被使用过。
    这种方法的实现复杂度是 O(|V|2) ,还可以优化。

  • 如果用一个优先队列把所有未使用过且最短距离(还不一定是最终最短距离)已知的顶点存起来,每次取队列底部的那个元素扩展,并将扩展得到的元素全部插入优先队列,这样删除插入的效率都是 O(log|V|) ,整个算法的效率就是 O(|E|log|V|)

我的思路:

  • 先求出到所有顶点的最短路。然后次短路无非是由最短路加上一条边,或最短路加上一条边得来,据此法则求次短路。要注意可以先到终点然后回去,再到终点。比如只有两个顶点,一个边的图,次短路是三倍边长。我的方法中,更新次短路用到的是Bellman-Ford算法的思想。

书上的思路:

  • 书上用的Dijstra算法实现,用dist[v]记录最短路,dist2[v]记录次短路,这样每次都按照规则更新最短路和次短路即可。

心得:

  • 学习算法的时候不要想着记忆具体实现,而是只关注抽象思维部分,具体实现由抽象思维得出即可
#include <set>
#include <map>
#include <cmath>
#include <stack>
#include <queue>
#include <string>
#include <vector>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long int LL;
const int M = 10009,INF = 0x3fffffff;
int v, e;
struct edge { int from, to, cost; }E[300009];
pair<int, int> d[M];

void input(void) {
    for (int i = 0; i < e / 2; i++) {
        scanf("%d%d%d", &E[i].from, &E[i].to, &E[i].cost);
        E[i].from--;
        E[i].to--;
        E[e / 2 + i].from = E[i].to;
        E[e / 2 + i].to = E[i].from;
        E[e / 2 + i].cost = E[i].cost;
    }
}

int second_shortest_path(void) {
    for (int i = 0; i < v; i++) { d[i].first = d[i].second = INF; }
    d[0].first = 0;
    edge temp;
    while (true) {
        bool update = false;
        for (int i = 0; i < e; i++) {
            temp = E[i];
            if (d[temp.from].first != INF && d[temp.to].first > d[temp.from].first + temp.cost) {
                d[temp.to].first = d[temp.from].first + temp.cost;
                update = true;
            }
        }
        if (!update) break;
    }
    while (true) {
        bool update = false;
        for (int i = 0; i < e; i++) {
            temp = E[i];
            //if (temp.from == v - 1) continue;
            if (d[temp.from].first != INF) {
                if (d[temp.to].second > d[temp.from].second + temp.cost && d[temp.from].second + temp.cost > d[temp.to].first) {
                    d[temp.to].second = d[temp.from].second + temp.cost;
                    update = true;
                }
                if (d[temp.to].second > d[temp.from].first + temp.cost && d[temp.from].first + temp.cost > d[temp.to].first) {
                    d[temp.to].second = d[temp.from].first + temp.cost;
                    update = true;
                }
            }
        }
        //cout << d[ v -1].first << endl;
        if (!update && d[v - 1].second != INF) break;
    }
    return d[v - 1].second;
}

int main(void) {
    //problem: , address:
    while (~scanf("%d%d", &v, &e)) {
        e = e * 2;
        input();
        printf("%d\n", second_shortest_path());
    }
    return 0;
}

你可能感兴趣的:(图)