1. 程式人生 > >POJ 3255 Roadblocks (Dijkstra求最短路徑的變形)(Dijkstra求次短路徑)

POJ 3255 Roadblocks (Dijkstra求最短路徑的變形)(Dijkstra求次短路徑)

ber emp accept backtrack cau scrip 直接 hang input

Roadblocks
Time Limit: 2000MS Memory Limit: 65536K
Total Submissions: 16425 Accepted: 5797

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: A, B, 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) 這題用Dijkstra算法求就可以了,我們維護兩個數組,d1[],d2[]。 d1保存最短路徑,d2保存次短路徑 我們考慮到,分兩種情況: 1.當我們隊列中的點沒有更新相鄰點的最短路徑,我們就用它更新次短路徑。 2.如果我們隊列中的點更新了相鄰點的最短路徑,我們就用原先的最短路徑更新次短路徑。 總而言之:   就是用所有非形成最短路徑的邊更新次短路徑。 Dijkstra算法求單元最短路徑:http://www.cnblogs.com/zhangjiuding/p/7712592.html 代碼:
#include <iostream>
#include <algorithm>
#include <stdio.h>
#include <vector>
#include <queue> 
using namespace std;
typedef long long ll;
#define MAX_N 5010
#define INF 2147483647

typedef pair<int,int> P; //first是最短距離,second是頂點編號 

struct edge{
    int to,cost;
};

int n,r;   //頂點數,邊數 
vector <edge> G[MAX_N]; //圖的鄰接表表示,G[x]表示點x相連的所有的邊的集合 

int dist1[MAX_N];   //最短路徑 
int dist2[MAX_N];   //次短路徑 

void solve(){
    //通過指定greater<P>參數,堆按照first從小到大的順序取出值。 
    priority_queue<P, vector<P>, greater<P> > que;
    fill(dist1, dist1+n, INF);
    fill(dist2, dist2+n, INF);
    dist1[0] = 0;
    que.push(P(0,0));
    
    
    while(!que.empty()){
        P p = que.top(); que.pop();
        int v = p.second, d = p.first;//取出編號和距離 
        
        //如果次短距離比之前加入這個點短,說明加入這個點之後又更新過
        //這裏continue相當於一種剪枝,沒有這句也不會錯,但是加了效率會變高 
        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(dist1[e.to] > d2){
                swap(dist1[e.to] ,d2); //把之前的距離取出來,更新次短路徑 
                que.push(P(dist1[e.to], e.to)) ;  // 把更新過的點加入隊列,用這個點去更新其他點 
            }
            //如果d2沒有更新過這個點的最短路徑,就直接用d2更新次短路徑
            //如果d2更新過這個點的最短路徑,就用d2交換出來的值更新次短路徑 
            if(dist2[e.to] > d2 && dist1[e.to] < d2){
                dist2[e.to] = d2;
                que.push(P(dist2[e.to], e.to));
            }
        }
    }
    printf("%d\n",dist2[n-1]);
} 

int main(){
    cin >> n >> r;
    int x,y,d;
    for(int i = 0;i < r; i++){
        edge e;
        cin >> x >> y >> d;
        e.cost = d;e.to = y-1;
        G[x-1].push_back(e);
        e.to = x-1;
        G[y-1].push_back(e);
    } 
    solve();
    return 0;
} 

POJ 3255 Roadblocks (Dijkstra求最短路徑的變形)(Dijkstra求次短路徑)