您的位置:首页 > Web前端 > JavaScript

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

2016-03-07 16:38 501 查看
①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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: