1. 程式人生 > >【POJ - 3255】Roadblocks(次短路 Dijkstra演算法)

【POJ - 3255】Roadblocks(次短路 Dijkstra演算法)

Roadblocks

直接翻譯了

Descriptions

Bessie搬到了一個新的農場,有時候他會回去看他的老朋友。但是他不想很快的回去,他喜歡欣賞沿途的風景,所以他會選擇次短路,因為她知道一定有一條次短路。
這個鄉村有R(1<=R<=100000)條雙向道路,每一條連線N(1<=N<=5000)個點中的兩個。Bessie在1號節點,他的朋友家是n號節點Input第一行:兩個整數N和R
接下來R行:每行包含三個整數,A,B,D,表示一條連線A與B的長度為D的路徑Output輸出1到n的次短路

Sample Input

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

Sample Output

450

Hint

兩條路線:1 - > 2 - > 4(長度100 + 200 = 300)和1 - > 2 - > 3 - > 4(長度100 + 250 + 100 = 450) 題目連結 https://vjudge.net/problem/POJ-3255  

求從s到t的次短路徑有兩種情況:1、起點s到某個頂點u的最短路+d(u,t)。2、起點到某個頂點u的次短路+d(u,t)。

所以更新路徑的時候需要把最短路徑和次短路徑兩個都記錄下來。

送一組資料

 

4 2
1 2 100
2 4 200
答案應該是500,然而如果初始化為0則答案會輸出700。因為500的結果是又1到2,在從2返回1,再到2,再到4,100+100+100+200=500得到的;如果次短邊初始化為0,則次短路徑不再返回源點,而是在2與4之間折返,會偏大。   AC程式碼
#include <iostream>
#include <cstdio>
#include <fstream>
#include <algorithm>
#include <cmath>
#include <deque>
#include <vector>
#include <queue>
#include <string>1
#include <cstring>
#include <map>
#include <stack>
#include <set>
#include <sstream>
#define IOS ios_base::sync_with_stdio(0); cin.tie(0)
#define Mod 1000000007
#define eps 1e-6
#define ll long long
#define INF 0x3f3f3f3f
#define MEM(x,y) memset(x,y,sizeof(x))
#define Maxn 5000+5
#define P pair<int,int>//first最短路徑second頂點編號
using namespace std;
int N,R;
struct edge
{
    int to,dis;
    edge(int to,int dis):to(to),dis(dis) {}
};
vector<edge>G[Maxn];//G[i] 從i到G[i].to的距離為dis
int d[Maxn][Maxn];//d[i][j]從i到j的最短距離
int d2[Maxn][Maxn];//d[i][j]從i到j的次短距離
void Dijk(int s)
{
    priority_queue<P,vector<P>,greater<P> >q;//按first從小到大出隊
    for(int i=0; i<=N; i++)//初始化s到所有地方的最短路,次短路都是inf
        d[s][i]=INF,d2[s][i]=INF;
    d[s][s]=0;
    q.push(P(0,s));
    while(!q.empty())
    {
        P p=q.top();
        q.pop();
        int v=p.second;//點v
        if(d2[s][v]<p.first)//大於次短路徑,肯定會大於最短路徑,不用管他了
            continue;
        for(int i=0; i<G[v].size(); i++)
        {
            edge e=G[v][i];//列舉與v相鄰的點
            int td=p.first+e.dis;//s到v的距離+v到e.to的距離
            if(d[s][e.to]>td)//s到e.to的最短路小於dt,更新d[s][e.to]
            {
                swap(d[s][e.to],td);
                q.push(P(d[s][e.to],e.to));
            }
            if(d[s][e.to]<td&&d2[s][e.to]>td)//td大於最短路,小於次短路,即td可以替換次短路
            {
                d2[s][e.to]=td;
                q.push(P(d2[s][e.to],e.to));
            }
        }
    }
}
int main()
{
    IOS;
    cin>>N>>R;
    for(int i=0; i<R; i++)
    {
        int u,v,d;
        cin>>u>>v>>d;
        G[u].push_back(edge(v,d));
        G[v].push_back(edge(u,d));
    }
    Dijk(1);//城市1到各個城市的最短距離,次短路
    cout<<d2[1][N]<<endl;
    return 0;
}