最短路 - spfa - (二) 【 理解 + 例题 】 更新 ing......
2014-08-11 13:46
246 查看
在家的学习效率实在太低,想想暑假都要过完了,什么东西都没学到。
如果你还没理解spfa 的过程,可以先看一下 最短路 - spfa - (一)
这篇文章的图解,接下来,我们就好好讲一讲spfa算法。
SPFA(Shortest Path Faster Algorithm)算法是求单源最短路径的一种算法,在Bellman-ford算法的基础上加上一个队列优化,减少了冗余的松弛操作是一种高效的最短路算法。相比于Dijkstra,SPFA可以计算带负环的回路。邻接表的复杂度为:O(kE)E为边数,k一般为2或3,k为所有顶点进队的平均次数。
过程:用数组dis记录更新后的状态,cnt记录更新的次数,队列q记录更新过的顶点,算法依次从q中取出待更新的顶点U,按照dis(k)[u]的递归式计算。在计算过程中,一旦发现顶点K有cnt[ k ] > n,说明有一个从顶点K出发的负权圈,此时没有最短路,应终止算法。否则,队列为空的时候,算法得到G的各顶点的最短路径长度。
关于松弛,个人感觉就是缩小路径上权值的上界。
负环的操作及判断,将在文末给出。
关于优化,将会在以后更新小讲一下。
下面来一个用邻接矩阵实现的模版吧,注意一下初始化和松弛操作
相信看完图解,可以很容易地理解。下面我们来看一些题目
第一题
POJ 2387 Til the Cows Come Home http://poj.org/problem?id=2387
本题就是很普通的最短路了,输入n, m,求1 到 n 的最短的距离,你可以用其它方法A掉,但是今天我们用一下spfa, 还有就是这几天看了好久的邻接表,所以这题就用邻接表来吧,过几天,会写一篇关于邻接表的。
关于负环的操作
下面给个 “所谓的模版” ,具体还是要看题意,也要注意各种初始化的问题
练习(你可以尝试各种最短路的算法,提高对算法的熟练度)
HDU 1874 畅通工程续 http://acm.hdu.edu.cn/showproblem.php?pid=1874
POJ 1201 Intervals http://poj.org/problem?id=1201
如果你还没理解spfa 的过程,可以先看一下 最短路 - spfa - (一)
这篇文章的图解,接下来,我们就好好讲一讲spfa算法。
SPFA(Shortest Path Faster Algorithm)算法是求单源最短路径的一种算法,在Bellman-ford算法的基础上加上一个队列优化,减少了冗余的松弛操作是一种高效的最短路算法。相比于Dijkstra,SPFA可以计算带负环的回路。邻接表的复杂度为:O(kE)E为边数,k一般为2或3,k为所有顶点进队的平均次数。
过程:用数组dis记录更新后的状态,cnt记录更新的次数,队列q记录更新过的顶点,算法依次从q中取出待更新的顶点U,按照dis(k)[u]的递归式计算。在计算过程中,一旦发现顶点K有cnt[ k ] > n,说明有一个从顶点K出发的负权圈,此时没有最短路,应终止算法。否则,队列为空的时候,算法得到G的各顶点的最短路径长度。
关于松弛,个人感觉就是缩小路径上权值的上界。
负环的操作及判断,将在文末给出。
关于优化,将会在以后更新小讲一下。
下面来一个用邻接矩阵实现的模版吧,注意一下初始化和松弛操作
void SPFA(int s) { for(int i = 0; i < n; i ++) dis[i] = INF; vis[s] = true; dis[s] = 0; queue<int> q; q.push(s); while(!q.empty()) { int cur = q.front(); q.pop(); vis[cur] = false; for(int i = 0; i < n; i ++) { if(dis[cur] + map[cur][i] < dis[i]) { dis[i]=dis[cur] + map[cur][i]; if(!vis[i]) { q.push(i); vis[i] = true; } } } } }
相信看完图解,可以很容易地理解。下面我们来看一些题目
第一题
POJ 2387 Til the Cows Come Home http://poj.org/problem?id=2387
本题就是很普通的最短路了,输入n, m,求1 到 n 的最短的距离,你可以用其它方法A掉,但是今天我们用一下spfa, 还有就是这几天看了好久的邻接表,所以这题就用邻接表来吧,过几天,会写一篇关于邻接表的。
#include<stdio.h> #include<queue> #include<string.h> #include<algorithm> using namespace std; #define N 2005 #define INF 1 << 29 struct Edge { int to, next, dis; }edge[2 * N]; int head ; int d ; bool vis ; int n, m; int k; void init() { memset(head, -1 , sizeof(head)); k = 1; } void addedge(int s, int t, int dist) // 用邻接表实现图的存储 { edge[k].to = t; edge[k].dis = dist; edge[k].next = head[s]; head[s] = k ++; } int spfa(int s) // spfa 操作,如有问题,可以参看上一篇的spfa图解 { queue<int> que; for(int i = 1; i <= n; i ++) d[i] = INF; d[s] = 0; memset(vis, 0, sizeof(vis)); que.push(s); while(!que.empty()) { int t = que.front(); que.pop(); vis[t] = false; for(int i = head[t]; i != -1; i = edge[i].next) { int v = edge[i].to; // 起点 int w = edge[i].dis; // 距离 if(d[v] > d[t] + w) { d[v] = d[t] + w; if(!vis[v]) // 若该点未在队列中,将改点拉入队列 { que.push(v); vis[v] = true; } } } } return d ; // 返回1 到 n 的距离,即本题的答案 } int main() { while(~scanf("%d%d",&n,&m)) { int a, b, c; init(); for(int i = 1; i <= m; i ++) { scanf("%d%d%d",&a,&b,&c); addedge(a, b, c); // 无向图,首尾都来一次 addedge(b, a, c); } printf("%d\n", spfa(1)); } return 0; }
关于负环的操作
下面给个 “所谓的模版” ,具体还是要看题意,也要注意各种初始化的问题
struct edge { int to, next, dis; }e[MAX]; bool spfa() { for(int i = 0; i <= n; i ++) dis[i] = INF; queue<int> q; dis[0] = 0; vis[0] = true; cnt[0] = 1; q.push(0); while(!q.empty()) { int cur = q.front(); q.pop(); vis[cur] = false; for(int i = head[cur]; i != -1; i = e[i].next) { int id = e[i].to; if(dis[cur] + e[i].dis > dis[id]) { dis[id] = dis[cur] + e[i].dis; if(!vis[id]) { cnt[id] ++; if(cnt[cur] > n) return false; vis[id] = true; q.push(id); } } } } return true; }
练习(你可以尝试各种最短路的算法,提高对算法的熟练度)
HDU 1874 畅通工程续 http://acm.hdu.edu.cn/showproblem.php?pid=1874
POJ 1201 Intervals http://poj.org/problem?id=1201
相关文章推荐
- 最短路 - floyd 【 理解 + 例题 】 更新 ing...
- 树状DP 小讲 【 理解 + 例题 】 更新 ing......
- 鸽笼原理 小讲 【 理解 + 例题 】 更新 ing ...
- KMP小讲 【理解 + 例题】 更新 ing.....
- 欧几里德与扩展欧几里德 小讲 【 理解 + 例题 】 更新 ing
- 二叉排序树(BST) 小讲 【 理解 + 例题 】 更新ing ...
- 网络流 - Edmond-Karp 小讲 【 理解 + 例题 】 更新 ing...
- 逆序数 小讲 【 理解 + 例题 】 更新ing....
- 最小生成树 - prim 小讲 【 理解 + 例题 】 更新 ing...
- 数位DP 小讲 【 理解 + 例题 】 更新 ing......
- 快速排序 小讲 - (二)【 理解 + 例题 】 更新 ing...
- 二分搜索 小讲 【 理解 + 例题 】 更新ing......
- stirling数 小讲 【 理解 + 例题 】 ing...
- 最短路(常用算法)----更新ing
- codevs5172 装病的聚聚 (最短路spfa的延伸应用)(对三角不等式的深入理解)--by lethalboy
- sql小知识(转载整理,逐步更新ing)
- XML备忘录(更新ing......)
- 好书推荐(持续更新ing)
- 问题集锦[更新ing]
- 纯平滑盖计算器(更新ing)