自己的第一道spfa,纪念一下,顺便转载一下spfa的原理。先po代码:

#include <iostream>
#include <queue>
using namespace std; const int MAX = ;
const int MAXN = ; int minimum(int a, int b){
return a > b ? b : a;
} int main()
{
int t;
cin >> t;
while (t--){
int n, m, w;
cin >> n >> m >> w;
int field[MAXN];
bool visited[MAXN];
int edge[MAXN][MAXN];
int visitCnt[MAXN];
memset(field, MAX, sizeof(field));
memset(edge, MAX, sizeof(edge));
memset(visited, , sizeof(visited));
memset(visitCnt, , sizeof(visitCnt));
for (int i = ; i < m; i++){
int field1, field2, len;
cin >> field1 >> field2 >> len;
edge[field1][field2] = minimum(edge[field1][field2], len);
edge[field2][field1] = minimum(edge[field2][field1], len);
}
for (int i = ; i < w; i++){
int field1, field2, len;
cin >> field1 >> field2 >> len;
edge[field1][field2] = minimum(edge[field1][field2], (-) * len);
}
field[] = ;
queue<int> Q;
Q.push();
visited[] = true;
visitCnt[] = ;
bool flag = false;
while (!Q.empty()){
int current = Q.front();
Q.pop();
visited[current] = false;
for (int i = ; i <= n; i++){
int tmp = field[current] + edge[current][i];
if (tmp < field[i]){
field[i] = tmp;
if (!visited[i]){
Q.push(i);
visited[i] = true;
visitCnt[i]++;
if (visitCnt[i] > n){
flag = true;
break;
}
}
}
}
if (flag)
break;
}
if (flag){
cout << "YES" << endl;
}
else{
cout << "NO" << endl;
}
}
return ;
}

以下内容转自http://www.cnblogs.com/zgmf_x20a/archive/2008/12/18/1357737.html

求最短路径的算法有许多种,除了排序外,恐怕是OI界中解决同一类问题算法最多的了。最熟悉的无疑是Dijkstra,接着是Bellman-Ford,它们都可以求出由一个源点向其他各点的最短路径;如果我们想要求出每一对顶点之间的最短路径的话,还可以用Floyd-Warshall。

SPFA是这篇日志要写的一种算法,它的性能非常好,代码实现也并不复杂。特别是当图的规模大,用邻接矩阵存不下的时候,用SPFA则可以很方便地面对临接表。每个人都写过广搜,SPFA的实现和广搜非常相似。

如何求得最短路径的长度值?

首先说明,SPFA是一种单源最短路径算法,所以以下所说的“某点的最短路径长度”,指的是“某点到源点的最短路径长度”。

我们记源点为S,由源点到达点i的“当前最短路径”为D[i],开始时将所有D[i]初始化为无穷大,D[S]则初始化为0。算法所要做的,就是在运行过程中,不断尝试减小D[]数组的元素,最终将其中每一个元素减小到实际的最短路径。

过程中,我们要维护一个队列,开始时将源点置于队首,然后反复进行这样的操作,直到队列为空:

(1)从队首取出一个结点u,扫描所有由u结点可以一步到达的结点,具体的扫描过程,随存储方式的不同而不同;

(2)一旦发现有这样一个结点,记为v,满足D[v] > D[u] + w(u, v),则将D[v]的值减小,减小到和D[u] + w(u, v)相等。其中,w(u, v)为图中的边u-v的长度,由于u-v必相邻,所以这个长度一定已知(不然我们得到的也不叫一个完整的图);这种操作叫做松弛。

松弛操作的原理是著名的定理:“三角形两边之和大于第三边”,在信息学中我们叫它三角不等式。所谓对i,j进行松弛,就是判定是否d[j]>d[i]+w[i,j],如果该式成立则将d[j]减小到d[i]+w[i,j],否则不动。

(3)上一步中,我们认为我们“改进了”结点v的最短路径,结点v的当前路径长度D[v]相比于以前减小了一些,于是,与v相连的一些结点的路径长度可能会相应地减小。注意,是可能,而不是一定。但即使如此,我们仍然要将v加入到队列中等待处理,以保证这些结点的路径值在算法结束时被降至最优。当然,如果连接至v的边较多,算法运行中,结点v的路径长度可能会多次被改进,如果我们因此而将v加入队列多次,后续的工作无疑是冗余的。这样,就需要我们维护一个bool数组Inqueue[],来记录每一个结点是否已经在队列中。我们仅将尚未加入队列的点加入队列。

算法能否结束?

对于不存在负权回路的图来说,上述算法是一定会结束的。因为算法在反复优化各个最短路径长度,总有一个时刻会进入“无法再优化”的局面,此时一旦队列读空,算法就结束了。然而,如果图中存在一条权值为负的回路,就糟糕了,算法会在其上反复运行,通过“绕圈”来无休止地试图减小某些相关点的最短路径值。假如我们不能保证图中没有负权回路,一种“结束条件”是必要的。这种结束条件是什么呢?

思考Bellman-Ford算法,它是如何结束的?显然,最朴素的Bellman-Ford算法不管循环过程中发生了什么,一概要循环|V|-1遍才肯结束。凭直觉我们可以感到,SPFA算法“更聪明一些”,就是说我们可以猜测,假如在SPFA中,一个点进入队列——或者说一个点被处理——超过了|V|次,那么就可以断定图中存在负权回路了。

最短路径本身怎么输出?

在一幅图中,我们仅仅知道结点A到结点E的最短路径长度是73,有时候意义不大。这附图如果是地图的模型的话,在算出最短路径长度后,我们总要说明“怎么走”才算真正解决了问题。如何在计算过程中记录下来最短路径是怎么走的,并在最后将它输出呢?

Path[]数组,Path[i]表示从S到i的最短路径中,结点i之前的结点的编号。注意,是“之前”,不是“之后”。最短路径算法的核心思想成为“松弛”,原理是三角形不等式,方法是上文已经提及的。我们只需要在借助结点u对结点v进行松弛的同时,标记下Path[v] = u,记录的工作就完成了。

输出时可能会遇到一点难处,我们记的是每个点“前面的”点是什么,输出却要从最前面往最后面输,这不好办。其实很好办,见如下递归方法:

void PrintPath(int k){
    if( Path[k] ) PrintPath(Path[k]);
    fout<<k<<' ';
}

最新文章

  1. 【转】oracle中in和exists的区别
  2. 关于Js添加版本号
  3. LeetCode:Container With Most Water,Trapping Rain Water
  4. 设计模式初学者笔记:Factory Method模式
  5. 33.allegro中Autosilk top, Silkscreen top 和Assembly top三个什么区别(转)
  6. IIS Session问题解决
  7. Android推送通知指南
  8. BZOJ 3677 连珠线
  9. Python Cookie HTTP获取cookie并处理
  10. Python实现Hadoop MapReduce程序
  11. Alamofire源码解读系列(五)之结果封装(Result)
  12. Ta-lib函数功能列表
  13. 团队作业4——第一次项目冲刺(Alpha版本)2st day
  14. Java中的Unsafe类111
  15. 第二节 pandas 基础知识
  16. 父元素高度设置为min-height,子元素高度设置为100%,但实际上子元素高度你知道是多少吗?
  17. 【Tomcat】Tomcat工作原理
  18. RPC 原理
  19. C# Windows Service中执行死循环轮询
  20. C# 一些代码小结--使用文件记录日志

热门文章

  1. Codeforces 803E - Roma and Poker
  2. 【洛谷 P2472】 [SCOI2007]蜥蜴 (最大流)
  3. sublime格式化css代码插件:css format
  4. HTTP、HTTPS
  5. app 测试基础
  6. Lucene7.2.1系列(二)luke使用及索引文档的基本操作
  7. 16 - 文件操作-StringIO-BytesIO
  8. python不可以打印.doc文件
  9. Tutorial 5: Relationships &amp; Hyperlinked APIs
  10. java版云笔记(五)