1. 程式人生 > >poj3255 次短路Dijkstra

poj3255 次短路Dijkstra

挑戰程式設計競賽上的題目。

題意:給一個邊權都是正的無向圖,求1到n的次短路。

分析:

考慮s->v的次短路,假設s-v的最短路為s->...->u>v,到v的次短路等於到u的次短路加上cost(u,v)和到k的最短路加上cost(k,v)中的最小但是大於u->v的最短路的值。那麼只要保證在求最短路的過程中同時儲存次短路就可以了。

程式碼。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
#include <queue>
#define INF 0x7fffffff
using namespace std;
typedef pair<int,int> P;
struct edge{
    int to,v;
    edge(int to,int v):to(to),v(v){}
    edge(){}
};
const int maxn = 5005;
const int maxe = 100005;
int V,E;
vector<edge> g[maxn];
int d[maxn],d2[maxn];//最短距離和次短距離
void dijkstra(int s)
{
    priority_queue<P,vector<P>,greater<P> > pq;
    for(int i=1;i<=V;i++)
    {
        d[i]=INF;
        d2[i]=INF;
    }
    d[s]=0;
    pq.push(P(0,s));
    while(pq.size())
    {
        P nowe=pq.top();pq.pop();
        if(nowe.first>d2[nowe.second]) continue;  //如果這個距離比當前次短路長continue
        for(int v=0;v<(int)g[nowe.second].size();v++)
        {
            edge nexte=g[nowe.second][v];
            int dis=nowe.first+nexte.v;
            if(d[nexte.to]>dis)
            {
                swap(dis,d[nexte.to]);
                pq.push(P(d[nexte.to],nexte.to));
            }
            if(d2[nexte.to]>dis&&d[nexte.to]<dis)//保證最短路是小於這個次短路的
            {
                d2[nexte.to]=dis;
                pq.push(P(d2[nexte.to],nexte.to));//次短路的點進入pq
            }
        }
    }
}
int main()
{
    int s;//起點
    scanf("%d%d",&V,&E);
    {
        for(int i=1;i<=V;i++)
            g[i].clear();
        for(int i=1;i<=E;i++)
        {
            int f,t,v;
            scanf("%d%d%d",&f,&t,&v);
            g[f].push_back(edge(t,v));
            g[t].push_back(edge(f,v));
        }
        s=1;//這題預設起點為1
        dijkstra(s);
        printf("%d\n",d2[V]);
    }
    return 0;
}