POJ3255Roadblocks

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;
}




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值