poj3255:Roadblocks

求次短路径长度

这道题的做法和最短路径基本一致,唯一的不同点在于,在求出最短路径的情况下必须要保留下次短路径。对于Dijkstra判断中取出的每一个点,如果到它的最短距离大于当前该点的次短距离,则当前该点已经取到最短距离和次短距离,不进行操作,否则进行两次判断:如果小于最短边,则赋给最短变,并将原最短边成为次短边;或者如果大于最短边且小于次短边,则赋给次短边。两次完成之后均要加入队列。参考:https://www.cnblogs.com/iiyiyi/p/4706182.html

#include <iostream>
#include <stdio.h>
#include <queue>
#include <vector>
#include <climits>
using namespace std;

const int MAXV = 5000 + 10;
const int INF = INT_MAX;

//邻接表存储图
struct Edge{
    int to, cost;
    Edge(int t, int c): to(t), cost(c) {}
};
vector<Edge> G[MAXV];

//优先级队列中存储的邻接点结构
struct Point{
    int distance, vertex;
    Point(int d, int v): distance(d), vertex(v) {}
    /*此处重载<,目的是实现在优先级队列(默认是大根堆)中distance较小的在堆顶
     * distance大的优先级小*/
    bool operator < (const Point& p) const {
        return distance > p.distance;
    }
};

int dist[MAXV];     //最短距离
int dist2[MAXV];    //次短距离

void Dijkstra(int start, int n){
    priority_queue<Point> que;
    //注意此处初始化时dist和dist2均向后偏移,因为顶点编号为1~n,若为0~n-1则不需要偏移
    fill(dist + 1, dist + 1 + n, INF);
    fill(dist2 + 1, dist2 + 1 + n, INF);
    dist[start] = 0;
    que.push(Point(0, start));

    while(!que.empty()){
        Point p = que.top();
        que.pop();
        int v = p.vertex;
        int d = p.distance;
        /*若从优先级队列中取出的点的距离大于次短距离
         * 则最短距离和次短距离都已经更新过了,直接跳过这个点即可*/
        if (dist2[v] < d){
            continue;
        }
        for (int i = 0; i < G[v].size(); ++i) {
            Edge e = G[v][i];
            int d2 = d + e.cost;
            if(dist[e.to] > d2){    //需要更新最短距离
                swap(dist[e.to], d2);   //原来的dist变为次短距离,存于d2中
                que.push(Point(dist[e.to], e.to));
            }
            if(dist2[e.to] > d2 && dist[e.to] < d2){    //更新次短距离,且保证最短距离小于次短距离
                dist2[e.to] = d2;
                que.push(Point(dist2[e.to], e.to));
            }
        }
    }
}

int main(){
    int n, r;
    int a, b, d;
    scanf("%d%d", &n, &r);
    for (int i = 0; i < r; ++i) {
        scanf("%d%d%d", &a, &b, &d);
        G[a].push_back(Edge(b, d));
        G[b].push_back(Edge(a, d));
    }
    Dijkstra(1, n);
    printf("%d\n", dist2[n]);

    return 0;
}
posted @ 2022-02-15 12:00  dctwan  阅读(53)  评论(0编辑  收藏  举报