挑战程序设计竞赛上的题目。
题意:给一个边权都是正的无向图,求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;
}