1. POJ3255Roadblocks
这道题求次短路径。我是按照《挑战程序设计竞赛》这本书的代码来写的,我就来解释一下这本书关于这道题的写法。
首先,这本书提到“到某个顶点v的次短路要么是到其他某个顶点u的最短路再加上u->v的边(显然u->v并不形成源点到v的最短路),要么是到u的次短路再加上u->v的边(显然这里u->v的边就是源点到v的最短路了)。”而另外一些博文提到先求出源点到v的最短路,然后逐次替换每一条路径换上另外一条,判断新生成的路径中的最小值,这也是一种思路。
从代码来分析这本书的思想,作者用了下述的方法进行Dijkstra寻最短路。其实中心思想就是:先找出最短路,然后找出长于最短路的最短路(即次短路)。方法是找到比当前某点的最短距离dist[e.to]要短时的最短路方法,然后就按Dijkstra的方法更换,并且判断如果老的(被更换的)那条比次短距离dist2[e.to]要短时,那就也替换,相当于进行两次Dijkstra,根据不同的判断依据找出两条路。
while(!que.empty()){
P p = que.top();que.pop();
int v = p.second,d = p.first;
if(dist2[v] < d ) continue;
for(int i = 0;i <(int) G[v].size();i++){
edge &e = G[v][i];
int d2 = d + e.cost;
if(dist[e.to] > d2){
swap(dist[e.to],d2);
que.push(P(dist[e.to],e.to));
}
if(dist2[e.to] > d2 && dist[e.to] < d2){
dist2[e.to] = d2;
que.push(P(dist2[e.to],e.to));
}
}
}
直到第11行都是Dijkstra的普通方法,用于找到最短路。只是要注意这里用了swap函数,为什么要用这个函数呢,就是为了下面对次短路径进行判断时,要看这条被替换的旧的最短路径是不是比原有的次短路径要短;同时注意swap之后,假如第一个if经过的话第二个if的第二个判断条件肯定是对的,那就用第一个判断条件来找出最短的次短路径。如果没经过第一个if,那第二个if的第二个判断条件也肯定是对的,因此还是通过第一个判断条件来找最短的次短路径。意思就是,找到一条即比最短路dist[e.to]要长,又在对每个子路径的遍历中找到最短的一条,从而找到次短路径。
还要注意的是因为采用了优先队列,所以相当于广搜,所以正确性得到了保证。
但是这道题我用这个代码提交POJ,那里老是说我CE,我也不知道问题在哪,先把自己的想法写上去吧。
/*
* POJ3255Roadblocks.cpp
*
* Created on: 2014年7月16日
* Author: Prophet
*/
#include<stdio.h>
#include<algorithm>
#include<vector>
#include<queue>
using namespace std;
struct edge{
int to,cost;//to:到达的点;cost:边的权值
};
const int MAX_N = 100010;
#define INF 1000000
typedef pair<int,int> P;//first是最短距离,second是顶点的编号
vector<edge> G[MAX_N];
int dist[MAX_N];//记录最短路
int dist2[MAX_N];//记录次短路
int x,y,z;
int n,r;
int main(){
while(scanf("%d%d",&n,&r)!=EOF){
for(int i=0;i<n;i++)
G[i].clear();
for(int i=0;i<r;i++){
scanf("%d%d%d",&x,&y,&z);
x--;
y--;
G[x].push_back(edge{y,z});
G[y].push_back(edge{x,z});//双向
}
//**********解题部分**********
std::priority_queue<P,std::vector<P>,std::greater<P> > que;
std::fill(dist,dist+n,INF);
std::fill(dist2,dist2+n,INF);
dist[0]=0;
que.push(P(0,0));//距离原点(编号为0)的最短距离为0
while(!que.empty()){
P p = que.top();que.pop();
int v = p.second,d = p.first;
if(dist2[v] < d ) continue;
for(int i = 0;i <(int) G[v].size();i++){
edge &e = G[v][i];
int d2 = d + e.cost;
if(dist[e.to] > d2){
swap(dist[e.to],d2);
que.push(P(dist[e.to],e.to));
}
if(dist2[e.to] > d2 && dist[e.to] < d2){
dist2[e.to] = d2;
que.push(P(dist2[e.to],e.to));
}
}
}
printf("%d\n",dist2[3]);
}
return 0;
}