POJ 3255 Roadblocks 【次短路】

題目鏈接

題意

給N個節點,R條雙向邊求從結點1到N的次短路徑

分析

通過這個題學習了一下次短路的求法。求K短路可以用A*+Dijkstra,有機會再學一發。
求次短路可以改進一下求最短路的Dijkstra,對每個結點不僅記錄最短距離,同時也記錄其嚴格的次短距離(不能等於最短路),同時再把鬆弛的條件改爲滿足次短的情況。

具體來說,首先入隊的條件有兩個:小於最短距離,大於最短距離且小於次短距離。
if(dist[a.to]>d)
if(sdist[a.to]>d&&dist[a.to]<d)
其中要注意,更新了最短距離,原來的最短距離可能就成了次短距離,所以要麼再多寫一個判斷,要麼在第一種情況中把賦值變成swap
swap(dist[a.to],d);

同樣出隊的條件也應放寬到小於次短路徑
if(p.dis>sdist[p.to]) continue;

可以證明這種做法的正確性,每次均在最短距離和嚴格次短距離上去鬆弛出新的最短距離和次短距離。

AC代碼

//POJ 3255 Roadblocks
//AC 2016-08-09 09:29:14
//Second Shortest Path
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cctype>
#include <cstdlib>
#include <cstring>
#include <vector>
#include <set>
#include <string>
#include <map>
#include <queue>
#include <deque>
#include <list>
#include <sstream>
#include <stack>
using namespace std;

#define cls(x) memset(x,0,sizeof x)
#define inf(x) memset(x,0x3f,sizeof x)
#define neg(x) memset(x,-1,sizeof x)
#define ninf(x) memset(x,0xc0,sizeof x)
#define st0(x) memset(x,false,sizeof x)
#define st1(x) memset(x,true,sizeof x)
#define INF 0x3f3f3f3f
#define lowbit(x) x&(-x)
#define input(x) scanf("%d",&(x))
#define bug cout<<"here"<<endl;
//#define debug

int N,R;
const int maxn=5010;

struct node
{
    int to;
    int dis;
    bool operator < (const node & rhs)const
    {
        return dis>rhs.dis;
    }
}p,q;
vector<node> G[maxn];

int dist[maxn];
int sdist[maxn];

void dijkstra(int beg)
{
    priority_queue<node> DIJ;
    inf(dist);inf(sdist);
    dist[beg]=0;
    p.to=beg;
    p.dis=0;
    DIJ.push(p);
    while(!DIJ.empty())
    {
        p=DIJ.top();
        DIJ.pop();
        if(p.dis>sdist[p.to])
            continue;
        for(int i=0;i<G[p.to].size();++i)
        {
            node &a=G[p.to][i];
            int d=p.dis+a.dis;
            if(dist[a.to]>d)
            {
                swap(dist[a.to],d);
                q.to=a.to;
                q.dis=dist[a.to];
                DIJ.push(q);
            }
            if(sdist[a.to]>d&&dist[a.to]<d)
            {
                sdist[a.to]=d;
                q.to=a.to;
                q.dis=d;
                DIJ.push(q);
            }
        }
    }
    return;
}

int main()
{
    #ifdef debug
        freopen("E:\\Documents\\code\\input.txt","r",stdin);
        freopen("E:\\Documents\\code\\output.txt","w",stdout);
    #endif
    while(scanf("%d %d",&N,&R)!=EOF)
    {
        for(int i=0;i<=N;++i)
            G[i].clear();
        int a,b;
        for(int i=0;i<R;++i)
        {
            scanf("%d %d %d",&a,&b,&p.dis);
            p.to=b;
            G[a].push_back(p);
            p.to=a;
            G[b].push_back(p);
        }
        dijkstra(1);
        printf("%d\n",sdist[N]);
    }
    return 0;
}
發佈了54 篇原創文章 · 獲贊 3 · 訪問量 1萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章