poj 3255 Roadblocks(spfa次短路 || Dijsktra)

①Dijsktra(454ms)

dis[i][0]:表示最短路;dis[i][1]:表示次短路;

每个点用数组vis标记,最短路标记为vis[i][0],次短路标记为vis[i][1];

先把源点加入图中,然后对个边进行松弛,总共需要2*n-1次(n-1次更新最短路,n次更新次短路)

初始化dis[src][0]=0;

每次选取到i点的最短距离的点或者次短距离的点进行松弛,优先松弛最短路,最短路如果可以松弛那么次短路也需要松弛,否则选择松弛次短路,具体实现详见代码。

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<queue>
using namespace std;

const double eps=1e-3;
const int INF=0x3f3f3f3f;
const int maxn=5010;
int n,m;
int vis[maxn][2],dis[maxn][2],head[maxn];
int edgeNum;

struct Edge{
	int to;
	int w;
	int next;
}edge[200010];

void addEdge(int u,int v,int w){
	edge[edgeNum].to=v;
	edge[edgeNum].w=w;
	edge[edgeNum].next=head[u];
	head[u]=edgeNum++;
}

void Init(){
	memset(vis,0,sizeof(vis));
	memset(dis,INF,sizeof(dis));
	memset(head,-1,sizeof(head));
	edgeNum=0;
}

void Dijsktra(int src,int des){
	dis[src][0]=0;
	for(int i=1;i<2*n;i++){
		int pos,min=INF,flag=-1;
		for(int j=1;j<=n;j++){
			if(!vis[j][0]&&min>dis[j][0]){
				min=dis[pos=j][0];
				flag=0;
			}
			else if(!vis[j][1]&&min>dis[j][1]){
				min=dis[pos=j][1];
				flag=1;
			}
		}
		if(flag==-1) break;
		vis[pos][flag]=1;
		for(int j=head[pos];j!=-1;j=edge[j].next){
			int v=edge[j].to;
			if(dis[v][0]>min+edge[j].w){
				dis[v][1]=dis[v][0];
				dis[v][0]=min+edge[j].w;
			}
			else if(dis[v][1]>min+edge[j].w){
				dis[v][1]=min+edge[j].w;
			}
		}
	}
	printf("%d\n",dis[des][1]);
}

int main(){
#ifndef ONLINE_JUDGE
	freopen("test.in","r",stdin);
	freopen("test.out","w",stdout);
#endif
	while(~scanf("%d%d",&n,&m)){
		Init();
		int u,v,w;
		for(int i=0;i<m;i++){
			scanf("%d%d%d",&u,&v,&w);
			addEdge(u,v,w);
			addEdge(v,u,w);
		}
		Dijsktra(1,n);
	}
	return 0;
}



②A*+SPFA(157ms)

先用spfa或者dijsktra预处理点n到其他所有点的最短距离dis[i] {i=1,2,...,n-1};

然后BFS进行逐层往下搜索。

设计估价函数f=g+h,用优先队列维护,g为到当前点所花的最小费用,h为到点n所需要的最小费用,即dis[i],每次扩展优先选取总费用最小的点。

当所扩展的点为n的次数为2时,即为次短路。

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<queue>
using namespace std;

const double eps=1e-3;
const int INF=0x3f3f3f3f;
const int maxn=5010;
int n,m;
int vis[maxn],dis[maxn],head[maxn];
int edgeNum;

struct Edge{
	int to;
	int w;
	int next;
}edge[200010];

void addEdge(int u,int v,int w){
	edge[edgeNum].to=v;
	edge[edgeNum].w=w;
	edge[edgeNum].next=head[u];
	head[u]=edgeNum++;
}

void Init(){
	memset(vis,0,sizeof(vis));
	memset(dis,INF,sizeof(dis));
	memset(head,-1,sizeof(head));
	edgeNum=0;
}

void spfa(int src){
	queue<int>q;
	q.push(src);
	vis[src]=1;
	dis[src]=0;
	while(!q.empty()){
		int u=q.front();
		q.pop();
		vis[u]=0;
		for(int i=head[u];i!=-1;i=edge[i].next){
			int v=edge[i].to;
			if(dis[v]>dis[u]+edge[i].w){
				dis[v]=dis[u]+edge[i].w;
				if(!vis[v]){
					vis[v]=1;
					q.push(v);
				}
			}
		}
	}
}

struct node{
	int to;
	int g,h,f;
	bool operator<(const node &a)const {
		return f>a.f||(f==a.f&&g>a.g);
	}
};

void Astar(int src,int des){
	priority_queue<node>q;
	int cnt=0;
	node s,e;
	s.to=src;
	s.g=0;
	s.h=dis[src];
	s.f=s.g+s.h;
	q.push(s);
	while(!q.empty()){
		s=q.top();
		q.pop();
		if(s.to==des){
			cnt++;
			if(cnt==2){
				printf("%d\n",s.g);
				return ;
			}
		}
		int u=s.to;
		for(int i=head[u];i!=-1;i=edge[i].next){
			e.to=edge[i].to;
			e.g=s.g+edge[i].w;
			e.h=dis[edge[i].to];
			e.f=e.g+e.h;
			q.push(e);
		}
	}
}

int main(){
	while(~scanf("%d%d",&n,&m)){
		Init();
		int u,v,w;
		for(int i=0;i<m;i++){
			scanf("%d%d%d",&u,&v,&w);
			addEdge(u,v,w);
			addEdge(v,u,w);
		}
		spfa(n);
		Astar(1,n);
	}
	return 0;
}

你可能感兴趣的:(poj 3255 Roadblocks(spfa次短路 || Dijsktra))