题目链接:https://vjudge.net/problem/HDU-2544

题意:给n个点,m条边,求点1到点n的最短路。

思路:

  今天学了下bellman_ford,抄抄模板。dijkstra算法和该算法都是单源最短路径算法,但是dij不能适用含负权边的图。而bellman-ford算法适用于负权边,原理是进行n-1次松弛操作,每次都要对m条边进行松弛,所以算法复杂度是O(mn),比dijkstra要高。如果n-1次操作之后还能进行松弛,说明存在负环。

AC code:

  1. #include<cstdio>
  2. #include<algorithm>
  3. #include<cstring>
  4. using namespace std;
  5.  
  6. const int maxn=;
  7. const int maxm=;
  8. const int inf=0x3f3f3f3f;
  9. int n,m,dis[maxn],cnt,loop;
  10.  
  11. struct node{
  12. int u,v,w;
  13. }edge[maxm<<];
  14.  
  15. void adde(int u,int v,int w){
  16. edge[++cnt].v=v;
  17. edge[cnt].u=u;
  18. edge[cnt].w=w;
  19. }
  20.  
  21. void bellman_ford(int s){
  22. for(int i=;i<=n;++i)
  23. dis[i]=inf;
  24. dis[s]=;
  25. //n-1次松弛
  26. for(int i=;i<n;++i){
  27. bool ok=;
  28. for(int j=;j<=cnt;++j){
  29. int u=edge[j].u,v=edge[j].v,w=edge[j].w;
  30. if(dis[v]>dis[u]+w){
  31. dis[v]=dis[u]+w;
  32. ok=;
  33. }
  34. }
  35. if(!ok) break;
  36. }
  37. //loop=1说明存在负环
  38. for(int i=;i<=cnt;++i){
  39. int u=edge[i].u,v=edge[i].v,w=edge[i].w;
  40. if(dis[v]>dis[u]+w){
  41. loop=;
  42. break;
  43. }
  44. }
  45. }
  46.  
  47. int main(){
  48. while(scanf("%d%d",&n,&m),n||m){
  49. cnt=,loop=;
  50. for(int i=;i<=m;++i){
  51. int u,v,w;
  52. scanf("%d%d%d",&u,&v,&w);
  53. adde(u,v,w);
  54. adde(v,u,w);
  55. }
  56. bellman_ford();
  57. printf("%d\n",dis[n]);
  58. }
  59. return ;
  60. }

思路2:

spfa是bellman-ford的队列优化版本,使用条件一样,vis标记该点是否在队列中,被更新的结点如果不在队列中要重新入队。也可以用来求是否存在负环,用updcnt数组记录每个结点更新次数,如果==n说明更新了n次,即存在负环。

然后说一下spfa的时间复杂度是O(km),k为常数,但最坏情况是O(mn),比较毒瘤,慎用!

下面的代码是luoguP3385,判负环。

AC code:

  1. #include<cstdio>
  2. #include<algorithm>
  3. #include<cstring>
  4. #include<queue>
  5. using namespace std;
  6.  
  7. const int maxn=;
  8. const int maxm=;
  9. const int inf=0x3f3f3f3f;
  10. int T,n,m,head[maxn],vis[maxn],cnt,upd[maxn],dis[maxn];
  11.  
  12. struct node{
  13. int v,w,nex;
  14. }edge[maxm];
  15.  
  16. void adde(int u,int v,int w){
  17. edge[++cnt].v=v;
  18. edge[cnt].w=w;
  19. edge[cnt].nex=head[u];
  20. head[u]=cnt;
  21. }
  22.  
  23. bool spfa(){
  24. for(int i=;i<=n;++i)
  25. vis[i]=,upd[i]=,dis[i]=inf;
  26. queue<int> que;
  27. que.push();
  28. vis[]=,dis[]=,++upd[];
  29. while(!que.empty()){
  30. int u=que.front();que.pop();
  31. vis[u]=;
  32. for(int i=head[u];i;i=edge[i].nex){
  33. int v=edge[i].v,w=edge[i].w;
  34. if(dis[v]>dis[u]+w){
  35. dis[v]=dis[u]+w;
  36. if(!vis[v]){
  37. ++upd[v];
  38. if(upd[v]>n) return true;
  39. vis[v]=;
  40. que.push(v);
  41. }
  42. }
  43. }
  44. }
  45. return false;
  46. }
  47.  
  48. int main(){
  49. scanf("%d",&T);
  50. while(T--){
  51. scanf("%d%d",&n,&m);
  52. for(int i=;i<=n;++i)
  53. head[i]=;
  54. cnt=;
  55. for(int i=;i<=m;++i){
  56. int u,v,w;
  57. scanf("%d%d%d",&u,&v,&w);
  58. if(w<){
  59. adde(u,v,w);
  60. }
  61. else{
  62. adde(u,v,w);
  63. adde(v,u,w);
  64. }
  65. }
  66. if(spfa()) printf("YE5\n");
  67. else printf("N0\n");
  68. }
  69. return ;
  70. }

  拓展:

  bellman-ford算法还能用来求最长路或者是判断正环,只用改下松弛条件即可。改变dis数组的定义为从源点到其它结点最长路径的长度,初始化为0,松弛时,如果dis[v]<dis[u]+w,则更新,其它操作一样。入poj1860。

AC code:

  1. #include<cstdio>
  2. #include<cstring>
  3. #include<algorithm>
  4. #include<queue>
  5. using namespace std;
  6.  
  7. const int maxn=;
  8. int n,m,s,head[maxn],vis[maxn],upd[maxn],cnt;
  9. double V,dis[maxn];
  10.  
  11. struct node{
  12. int v,nex;
  13. double r,c;
  14. }edge[maxn<<];
  15.  
  16. void adde(int u,int v,double r,double c){
  17. edge[++cnt].v=v;
  18. edge[cnt].r=r;
  19. edge[cnt].c=c;
  20. edge[cnt].nex=head[u];
  21. head[u]=cnt;
  22. }
  23.  
  24. bool spfa(int s,double V){
  25. for(int i=;i<=n;++i) dis[i]=,vis[i]=,upd[i]=;
  26. dis[s]=V,vis[s]=;
  27. queue<int> que;
  28. que.push(s);
  29. ++upd[s];
  30. while(!que.empty()){
  31. int u=que.front();que.pop();
  32. vis[u]=;
  33. for(int i=head[u];i;i=edge[i].nex){
  34. int v=edge[i].v;
  35. double r=edge[i].r,c=edge[i].c;
  36. if(dis[v]<(dis[u]-c)*r){
  37. dis[v]=(dis[u]-c)*r;
  38. if(!vis[v]){
  39. ++upd[v];
  40. if(upd[v]>n) return true;
  41. que.push(v);
  42. vis[v]=;
  43. }
  44. }
  45. }
  46. }
  47. if(dis[s]>V) return true;
  48. return false;
  49. }
  50.  
  51. int main(){
  52. scanf("%d%d%d%lf",&n,&m,&s,&V);
  53. for(int i=;i<=n;++i) head[i]=;
  54. cnt=;
  55. for(int i=;i<=m;++i){
  56. int u,v;
  57. double ruv,cuv,rvu,cvu;
  58. scanf("%d%d%lf%lf%lf%lf",&u,&v,&ruv,&cuv,&rvu,&cvu);
  59. adde(u,v,ruv,cuv);
  60. adde(v,u,rvu,cvu);
  61. }
  62. if(spfa(s,V)) printf("YES\n");
  63. else printf("NO\n");
  64. return ;
  65. }

(模板)hdoj2544(最短路--bellman-ford算法&&spfa算法)的更多相关文章

  1. hdoj2544 最短路(Dijkstra || Floyd || SPFA)

    题目链接 http://acm.hdu.edu.cn/showproblem.php?pid=2544 思路 最短路算法模板题,求解使用的Dijkstra算法.Floyd算法.SPFA算法可以当做求解 ...

  2. 六度分离(floyd算法,SPFA算法,最短路—Dijkstra算法)

    Time Limit : 5000/1000ms (Java/Other)   Memory Limit : 32768/32768K (Java/Other) Total Submission(s) ...

  3. UESTC - 1987 童心未泯的帆宝和乐爷 (第k短路 A*算法+SPFA算法 模板)

    传送门: http://www.qscoj.cn/#/problem/show/1987 童心未泯的帆宝和乐爷 Edit Time Limit: 10000 MS     Memory Limit: ...

  4. Bellman-Ford算法与SPFA算法详解

    PS:如果您只需要Bellman-Ford/SPFA/判负环模板,请到相应的模板部分 上一篇中简单讲解了用于多源最短路的Floyd算法.本篇要介绍的则是用与单源最短路的Bellman-Ford算法和它 ...

  5. Bellman-ford算法、SPFA算法求解最短路模板

    Bellman-ford 算法适用于含有负权边的最短路求解,复杂度是O( VE ),其原理是依次对每条边进行松弛操作,重复这个操作E-1次后则一定得到最短路,如果还能继续松弛,则有负环.这是因为最长的 ...

  6. 2018/1/28 每日一学 单源最短路的SPFA算法以及其他三大最短路算法比较总结

    刚刚AC的pj普及组第四题就是一种单源最短路. 我们知道当一个图存在负权边时像Dijkstra等算法便无法实现: 而Bellman-Ford算法的复杂度又过高O(V*E),SPFA算法便派上用场了. ...

  7. (最短路径算法整理)dijkstra、floyd、bellman-ford、spfa算法模板的整理与介绍

    这一篇博客以一些OJ上的题目为载体.整理一下最短路径算法.会陆续的更新... 一.多源最短路算法--floyd算法 floyd算法主要用于求随意两点间的最短路径.也成最短最短路径问题. 核心代码: / ...

  8. 图论——最短路:Floyd,Dijkstra,Bellman-Ford,SPFA算法及最小环问题

    一.Floyd算法 用于计算任意两个节点之间的最短路径. 参考了five20的博客 Floyd算法的基本思想如下:从任意节点A到任意节点B的最短路径不外乎2种可能,1是直接从A到B,2是从A经过若干个 ...

  9. [板子]SPFA算法+链式前向星实现最短路及负权最短路

    参考:https://blog.csdn.net/xunalove/article/details/70045815 有关SPFA的介绍就掠过了吧,不是很赞同一些博主说是国内某人最先提出来,Bellm ...

随机推荐

  1. mac系统提示 interactive intelligence 的恼人问题

    处理 interacti intelligence 提示问题记录 二手购买了一台电脑,从最初的小白到现在稍微熟悉mac的使用, 一直困扰我的便是一个提示, 上图 困扰多年, 记录一下解决和尝试过程吧. ...

  2. CSS Sticky 其实很简单

    为什么要写这篇文章 Sticky 也不是新知识点了,写这篇文章的原因是由于最近在实现效果的过程中,发现我对 Sticky 的理解有偏差,代码执行结果不如预期.决定写篇文章重新学习一次. 什么是 Sti ...

  3. ubuntu之路——day11.1 如何进行误差分析

    举个例子 还是分类猫图片的例子 假设在dev上测试的时候,有100张图片被误分类了.现在要做的就是手动检查所有被误分类的图片,然后看一下这些图片都是因为什么原因被误分类了. 比如有些可能因为被误分类为 ...

  4. #C++初学记录(算法测试2019/5/5)(深度搜索)

    深度搜索:Oil Deposits GeoSurvComp地质调查公司负责探测地下石油储藏. GeoSurvComp现在在一块矩形区域探测石油,并把这个大区域分成了很多小块.他们通过专业设备,来分析每 ...

  5. 【转】JVM类装载机制的解析,热更新的探讨

    引言 如有错误,请批评指正. Java是一种动态连接的语言.所谓动态连接,大概可以这么解释. 首先,Java可以大概想象成是编译解释执行的.对于一个*.java的文件,通过javac将会编译成一个*. ...

  6. word: 插入或修改文字时后面的字消失 解决办法

    在编辑Word文档中的文字时,我们有时需要插入或修改文字,可是在插入或修改时会发现改动处后面的文字会消失.比如插入或修改3个字,后面的文字随之也会消失3个,这时该怎么办呢? 点击-“文件”-“选项”- ...

  7. 007 CSS基本选择器

    复习. 一:类选择器 1.多类名选择器 使用场景:某个标签上需要多个类进行描述. 多个类之间使用空格分开. 冲突的时候,和类名在html中的先后顺序没有关系,和css中的样式的先后顺序有关系. 2.案 ...

  8. Objective-C轻量级泛型

    在Apple发布Xcode7的时候,不仅把Swift编程语言升级到了2.0版本,而且还对Objective-C做了许多提升,包括引入__nonnull/__nullable.其中,对于Objectiv ...

  9. 实战二:LoadRunner创建一个测试脚本

    问题一:执行脚本浏览器不能自动启动??? 原因:loadrunner11只支持IE9以下浏览器和火狐低版本浏览器 解决办法:1.IE浏览器取消勾选[启用第三方浏览器扩展]启动IE,从[工具]进入[In ...

  10. 解决IE浏览器没有网络的情况

    计算机能够连接到网络,但是IE浏览器却显示没有网络. 解决方案: 设置 >> IE internet选项: 选择“高级”: 选择“重置”: 勾选“删除个人设置”,点击重置: 重新打开IE, ...