首页 > 代码库 > POJ 3255 Roadblocks (次短路径 + Dijkstra算法)

POJ 3255 Roadblocks (次短路径 + Dijkstra算法)

Roadblocks
Time Limit: 2000MS Memory Limit: 65536K
Total Submissions: 7982 Accepted: 2921

Description

Bessie has moved to a small farm and sometimes enjoys returning to visit one of her best friends. She does not want to get to her old home too quickly, because she likes the scenery along the way. She has decided to take the second-shortest rather than the shortest path. She knows there must be some second-shortest path.

The countryside consists of R (1 ≤ R ≤ 100,000) bidirectional roads, each linking two of the N (1 ≤ N ≤ 5000) intersections, conveniently numbered 1..N. Bessie starts at intersection 1, and her friend (the destination) is at intersection N.

The second-shortest path may share roads with any of the shortest paths, and it may backtrack i.e., use the same road or intersection more than once. The second-shortest path is the shortest path whose length is longer than the shortest path(s) (i.e., if two or more shortest paths exist, the second-shortest path is the one whose length is longer than those but no longer than any other path).

Input

Line 1: Two space-separated integers: N and R 
Lines 2..R+1: Each line contains three space-separated integers: AB, and D that describe a road that connects intersections A and B and has length D (1 ≤ D ≤ 5000)

Output

Line 1: The length of the second shortest path between node 1 and node N

Sample Input

4 4
1 2 100
2 4 200
2 3 250
3 4 100

Sample Output

450

Hint

Two routes: 1 -> 2 -> 4 (length 100+200=300) and 1 -> 2 -> 3 -> 4 (length 100+250+100=450)

Source

USACO 2006 November Gold



题意:某条街区共有R条道路,N个路口。道路可以双向通行。问1号路口到N号路口的次短路径长度是多少。次短路径是指所有路径中第二短的路径。并且同一条边可以经过多次。


解析:记最短路径长度为d[ ],次短路径长度为dd[ ],则d[v] = min( d[u] + cost[u][v],  dd[u] + cost[u][v] ),所以我们只需要计算出最短路径和次短路径即可。这就跟最短路径不一样了,在实现Dijkstra算法的时候,我们既要记录最短路径,还要记录次短路径。详见代码

PS:第一次写邻接表的形式写最短路,真是学到了!邻接表比邻接矩阵的时间复杂度要好很多,就是写着麻烦一点,不过习惯了就好^_^




AC代码:

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
using namespace std;
#define MAX_N 5005
#define INF 500000001

int N, R;
struct edge{ int to, cost; };
vector<edge> G[MAX_N];            //无向图的邻接表表示
int d[MAX_N], dd[MAX_N];          //d[]最短路,dd[]次短路

void solve(){
    typedef pair<int, int> P;
    priority_queue<P, vector<P>, greater<P> > q;       //优先级队列优化Dijkstra
    fill(d, d+N, INF);                                 //跟memset的作用是一样的,初始化数组
    fill(dd, dd+N, INF);
    d[0] = 0;
    q.push( P(0, 0) );

    while(!q.empty()){
        P p = q.top(); q.pop();
        int v = p.second, d1 = p.first;
        if(dd[v] < d1) continue;
        for(int i=0; i<G[v].size(); i++){
            edge e = G[v][i];
            int d2 = d1 + e.cost;
            if(d[e.to] > d2){                        //更新最短路
                swap(d[e.to], d2);
                q.push( P(d[e.to], e.to) );
            }
            if(dd[e.to] > d2 && d[e.to] < d2){       //更新次短路
                dd[e.to] = d2;
                q.push( P(dd[e.to], e.to) );
            }
        }
    }
    printf("%d\n", dd[N-1]);
}

int main(){
    #ifdef sxk
        freopen("in.txt", "r", stdin);
    #endif // sxk

    int to, from, cost;
    edge foo;
    while(scanf("%d%d", &N, &R)!=EOF){
        for(int i=0; i<R; i++){
            scanf("%d%d%d", &from, &to, &cost);
            from --;  to --;                       //编号换成0~N-1
            foo.to = to; foo.cost = cost;
            G[from].push_back(foo);
            foo.to = from;                         //双向边
            G[to].push_back(foo);                  
        }
        solve();
    }
    return 0;
}




POJ 3255 Roadblocks (次短路径 + Dijkstra算法)