题意
给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
",sdist[N]);
}
return 0;
}