SPFA的堆栈实现
2012-09-16 17:50
274 查看
算法简介
SPFA(Shortest Path Faster Algorithm)是Bellman-Ford算法的一种优化,减少了不必要的冗余计算。 它可以在O(kE)的时间复杂度内求出源点到其他所有点的最短路径,可以处理负边,但判断负回路不方便。
值得注意的是,得到可行解后,可以看成新的约束:xi-xj<=d[i]-d[j],即d[i]为xi-x0的最大值。由此可以看出,SPFA和Bellman-Ford算法解决差分约束系统问题时,实际上是把约束条件强化了,使得满足任意约束条件的值都能构造出一个完整的解。同样的,当约束方程为>=时,求出的xi-xj>=d[i]-d[j],故d[i]为xi-x0的最小值。理解后灵活运用,差分约束问题就比较容易解决了。(这里设x0为源点)
算法流程
SPFA对Bellman-Ford算法优化的关键之处在于意识到:只有那些在前一遍松弛中改变了距离估计值的点,才可能引起他们的邻接点的距离估计值的改变。因此,算法大致流程是用堆栈或队列存放被成功松弛的顶点。初始时,源点s入队。当队列不为空时,取出栈顶/队首顶点,对它的邻接点进行松弛。如果某个邻接点松弛成功,且该邻接点不在堆栈/队列中,则将其入栈/队。经过有限次的松弛操作后,堆栈/队列将为空,算法结束。
int N,M; //实际的顶点数和边数
struct Edge{
Edge* linklist[MAXN+1]={0}; //MAXN为最大顶点数
void SPFA( Edge* linklist[], int dist[], int source ){ //参数分别为边的临接表、距离、源点,堆栈实现
bool bInQ[MAXN+1]={0}; //判断点是否在堆栈中
int stack[MAXN+1]={0}, top=0; //保存活动结点
for( int i= 1; i<= N; i++ )
dist[i]= INF;
dist[source]= 0;
stack[top++]= source;
while( top ){
int cur= stack[--top];
Edge* q= linklist[cur];
bInQ[cur]= 0;
while( q ){
if( dist[q->to]> dist[cur]+q->cost ){
dist[q->to]= dist[cur]+q->cost;
if( !bInQ[q->to] )
stack[top++]= q->to;
bInQ[q->to]=1;
}
q=q->next;
}
}
}
转自:http://www.cppblog.com/guyuecanhui/articles/80883.html
SPFA(Shortest Path Faster Algorithm)是Bellman-Ford算法的一种优化,减少了不必要的冗余计算。 它可以在O(kE)的时间复杂度内求出源点到其他所有点的最短路径,可以处理负边,但判断负回路不方便。
值得注意的是,得到可行解后,可以看成新的约束:xi-xj<=d[i]-d[j],即d[i]为xi-x0的最大值。由此可以看出,SPFA和Bellman-Ford算法解决差分约束系统问题时,实际上是把约束条件强化了,使得满足任意约束条件的值都能构造出一个完整的解。同样的,当约束方程为>=时,求出的xi-xj>=d[i]-d[j],故d[i]为xi-x0的最小值。理解后灵活运用,差分约束问题就比较容易解决了。(这里设x0为源点)
算法流程
SPFA对Bellman-Ford算法优化的关键之处在于意识到:只有那些在前一遍松弛中改变了距离估计值的点,才可能引起他们的邻接点的距离估计值的改变。因此,算法大致流程是用堆栈或队列存放被成功松弛的顶点。初始时,源点s入队。当队列不为空时,取出栈顶/队首顶点,对它的邻接点进行松弛。如果某个邻接点松弛成功,且该邻接点不在堆栈/队列中,则将其入栈/队。经过有限次的松弛操作后,堆栈/队列将为空,算法结束。
int N,M; //实际的顶点数和边数
struct Edge{
Edge* linklist[MAXN+1]={0}; //MAXN为最大顶点数
void SPFA( Edge* linklist[], int dist[], int source ){ //参数分别为边的临接表、距离、源点,堆栈实现
bool bInQ[MAXN+1]={0}; //判断点是否在堆栈中
int stack[MAXN+1]={0}, top=0; //保存活动结点
for( int i= 1; i<= N; i++ )
dist[i]= INF;
dist[source]= 0;
stack[top++]= source;
while( top ){
int cur= stack[--top];
Edge* q= linklist[cur];
bInQ[cur]= 0;
while( q ){
if( dist[q->to]> dist[cur]+q->cost ){
dist[q->to]= dist[cur]+q->cost;
if( !bInQ[q->to] )
stack[top++]= q->to;
bInQ[q->to]=1;
}
q=q->next;
}
}
}
转自:http://www.cppblog.com/guyuecanhui/articles/80883.html
相关文章推荐
- poj 3159 分糖果 第一次差分约束+ 用堆栈实现spfa(更快)
- SPFA的堆栈实现
- PHP基于堆栈实现的高级计算器功能示例
- 类模板实现堆栈
- java数据结构-链表实现堆栈 控制插入的方式,成为有序链表
- 图的深度优先遍历(堆栈实现和非堆栈实现)
- js里实现队列与堆栈
- 利用堆栈和队列实现计算器
- VBS 脚本中的字典、动态数组、队列和堆栈实现代码
- VB利用堆栈实现表达式计算
- android java 堆栈的实现
- 算法面试题:使用两个堆栈实现一个队列
- 基于链表实现堆栈
- 堆栈实现
- Cracking coding interview(3.1)用一个数组实现3个堆栈
- 斐波那契堆栈实现(递归的代码实现)
- 另一版本的基于堆栈的虚拟机实现
- shell脚本实现堆栈(模拟合服)
- 实现C++堆栈模板
- java实现堆栈