针对Bellman-Ford算法效率比较低的问题,SPFA是用一个队列来进行维护。初始时将源加入队列。每次从队列中取出一个元素,并对所有与他相邻的点进行松弛,若某个相邻的点松弛成功,则将其入队。直到队列为空时算法结束。它可以在O(kE)的时间复杂度内求出源点到其他所有点的最短路径,有办法证明对于通常的情况,k在2左右。
值得注意的一点是,如果某个点进入队列的次数超过V次则图中存在负环(SPFA无法处理带负环的图)。
#include<iostream> #include<vector> #include<queue> #include<cstring> using namespace std; class node { public: int r,c; node(){} node(int r,int c):r(r),c(c){} }; class edge { public: int sr,sc,er,ec; int cost; edge(){} edge(int sr,int sc,int er,int ec,int cost):sr(sr),sc(sc),er(er),ec(ec),cost(cost) { } }; int n,m,r,c; int map[31][31]; int dist[31][31]; int flag[31][31]; const int maximum=1<<30; vector<edge>a[31][31]; void init() { for(int i=0;i<n;i++) for(int j=0;j<m;j++) a[i][j].clear(); for(int i=0;i<n;i++) { for(int j=0;j<m;j++) { if(map[i][j]==0) continue; int d; int west=j-map[i][j]; if(west<0) { edge e(i,j,i,0,map[i][j]); a[i][j].push_back(e); } else { edge e(i,j,i,west,map[i][j]); a[i][j].push_back(e); } int east=j+map[i][j]; if(east>=m) { edge e(i,j,i,m-1,map[i][j]); a[i][j].push_back(e); } else { edge e(i,j,i,east,map[i][j]); a[i][j].push_back(e); } int north=i-map[i][j]; if(north<0) { edge e(i,j,0,j,map[i][j]); a[i][j].push_back(e); } else { edge e(i,j,north,j,map[i][j]); a[i][j].push_back(e); } int south=i+map[i][j]; if(south>=n) { edge e(i,j,n-1,j,map[i][j]); a[i][j].push_back(e); } else { edge e(i,j,south,j,map[i][j]); a[i][j].push_back(e); } } } } bool SPFA() { for(int i=0;i<n;i++) for(int j=0;j<m;j++) dist[i][j]=maximum; memset(flag,0,sizeof(flag)); dist[r-1][c-1]=0; queue<node>q; q.push(node(r-1,c-1)); flag[r-1][c-1]=1;; while(!q.empty()) { node n=q.front(); q.pop(); int row=n.r; int col=n.c; flag[row][col]=0; int size=a[row][col].size(); for(int i=0;i<size;i++) { int startr=(a[row][col])[i].sr; int startc=(a[row][col])[i].sc; int endr=(a[row][col])[i].er; int endc=(a[row][col])[i].ec; int cost=(a[row][col])[i].cost; if(dist[startr][startc]!=maximum&&dist[startr][startc]+cost<dist[endr][endc]) { dist[endr][endc]=dist[startr][startc]+cost; if(flag[endr][endc]==0) { q.push(node(endr,endc)); flag[endr][endc]==1; } } } } return true; } int main() { while(cin>>n>>m>>r>>c) { int fr,fc; for(int i=0;i<n;i++) for(int j=0;j<m;j++) { cin>>map[i][j]; if(map[i][j]==0) { fr=i; fc=j; } } init(); SPFA(); if(dist[fr][fc]!=maximum) cout<<dist[fr][fc]<<endl; else cout<<"No solution"<<endl; } }
发表评论
-
图的割点tarjan---zoj_1119
2011-10-24 23:00 1236http://acm.zju.edu.cn/on ... -
BFS与双向BFS---zoj_1505
2011-10-09 17:14 1647http://acm.zju.edu.c ... -
静态treap+线段树---zoj_2112
2011-09-29 23:06 1712http://acm.zju.edu ... -
NIM博弈游戏,SG函数---zoj_3084,zoj_2083
2011-09-23 23:00 1322Nim游戏是两个人进行的游戏有如下规则: ... -
多重背包--zoj_2156
2011-09-14 11:10 867首先介绍经典的三种背包问题,0-1背包,完全 ... -
模式串匹配---KMP
2011-08-31 20:49 1282朴素的的模式串匹配算法通常要在向前移动文本指针 ... -
八数码问题(A*&&双向BFS)---zoj_1217
2011-08-30 22:13 1673题目地址:http://acm.zju.edu.cn/onli ... -
ac自动机以及它上面的DFA
2011-08-08 23:04 2483AC自动机(Aho-Corasick)主要用 ... -
二分图最大匹配(匈牙利算法)--zoj1516,1525,2223
2011-07-20 22:36 1190二分图G(E,V)将点集合V分成两个部分L,R ... -
网络最大流(EK)---zoj_1734
2011-07-19 16:34 2136网络最大流是图论中的一个典型问题,为了精确的定 ... -
trie和前缀检查---zoj_2876
2011-07-13 23:03 871trie树是一种多叉树,广泛用于字典检索。如 ... -
位图bitmap
2011-07-13 21:08 916bitmap是一种广泛使用的数据结构,主要用在 ... -
LAC和RMQ的转化---zoj_3195
2011-07-12 22:35 1078我擦。。纠结了好久啊,从SF到TLE,先总结2 ... -
LAC的tarjan(离线)算法---zoj_1141
2011-07-08 17:52 1662LCA就不解释了,这里主要再次复习一下LC ... -
笛卡尔树以及treap---zoj_2243
2011-07-07 15:52 2847zoj_2243笛卡 ... -
线段染色,矩形切割,离散化---zoj_2301,zoj_1128
2011-06-24 22:32 1369染色问题:在一维坐标轴上(最右端为M),有N ... -
线段树---zoj_1610
2011-06-22 21:06 756线段树是一种二叉树的拓展,在线段树每个节点中 ... -
快速排序(qsort)
2011-06-16 17:03 782快速排序是一种高效的非稳定排序,它的基本思路 ... -
斐波那契散列
2011-06-16 16:38 3083斐波那契散列法其实是一种特殊的乘法散列,先来看乘法 ... -
强连通分支(scc)---tarjan
2011-06-15 16:17 1285本文大量 ...
相关推荐
单源最短路径--分支限界法
用贪心算法解单源最短路径问题 明确单源最短路径问题的概念;利用贪心算法解决单源最短路径问题;并通过本例熟悉贪心算法在程序设计中的应用方法。
1.分支限界法求解单源最短路径 2.C++源码+程序说明文档 3.源码带详细注释
经典算法单源最短路径经典算法单源最短路径经典算法单源最短路径经典算法单源最短路径经典算法单源最短路径
关于单源最短路径的问题非常典型,这里没有给出分析与证明,仅仅给出了实现。 需要指出的是,许多实现仅给出了最短路径的长度,而没有给出“最短路径”,这里用给出了实现。 如程序中那样,定义一个数组p[N],其中...
A、掌握图中单源最短路径的概念; B、掌握Dijkstra算法的原理;
单元最短路径,为广大计算机专业学生算法所需实验报告而准备
有很长时间没有上传了,主要是因为这些天出了些小事。这个是用分支限界法求解单源最短路径问题的算法。
单源最短路径C语言实现,简单易懂,适合算法学习
分支限界法 (1)描述:采用广度优先产生状态空间树的结点,并使用剪枝函数的方法称为分枝限界法。 所谓“分支”是采用广度优先的策略,依次生成扩展结点的所有分支(即:儿子结点)。 所谓“限界”是在结点扩展...
算法设计与分析课内实验——动态规划求单源最短路径。文档很齐全,包括算法分析过程和源代码(java语言eclipse环境)
在算法中,利用结点间的控制关系进行剪枝。从源顶点s出发,2条不同路径到达图G的同一顶点。由于两条路径的路长不同,因此可以将路长长的路径所对应的树中的结点为根的子树剪去。
基于贪心法求解单源最短路径问题 完整实验报告,结尾有实验代码
给定一个带权有向图 G=(V,E) ,其中每条边的权是一个整数。另外,还给定 V 中的一个顶点,称为源。现在我们要计算从源到所有其他各顶点的最短路径长度。这里的长度是指路上各边权...这个问题通常称为单源最短路径问题。
用python实现迪杰斯特拉算法,单源最短路径,有向图权值无负值,用邻接矩阵来存储有向图,实现路径存储和路径打印
算法设计与分析实验报告,附已通过源码,供学习参考,共勉♪ 目录摘要如下: 1.问题描述 2.实验目的 3.实验原理 4.实验设计 ...(包括输入格式、算法、输出格式) ...(除了截图外,实验结果还用图表进行了分析) ...
用C++实现的贪心算法 Dijkstra 单源最短路径,并包含大量的注释,对理解程序很有帮助
这是算法分析中实现单源最短路径问题的C++程序
Dijstra算法用于求解单源最短路径问题,即在图中求出给定顶点到其它任一顶点的最短路径。
用Dijkstra算法实现单源最短路径问题。 第一行:n。代表n个顶点。其中第一个顶点为源点 第二行:c11 c12 c13....c1n (以下n行合起来为n*n的权矩阵,cij代表了i点到j点的边的权值,-1代表无穷大.每行n个数,数与...