最短路径

1.Dijkstra算法

主要解决单源最短路径问题:

void Dijkstra(int s){for(int i = 0;i < maxn;i++)dis[i] = INF;dis[s] = 0;for(int i = 0;i < n;i++){int u = -1,min = INF;for(int j = 0;j < n;j++){if(!visit[j] && dis[j] < INF){u = j;min = dis[j];}}if(u == -1)  return;visit[u] = true;for(int j = 0;j < n;j++){if(!visit[j] && G[u][j] != INF){if(dis[j] > dis[u] + G[u][j]){dis[j] = dis[u] + G[u][j];}}}}}

当有两种或以上的最短路径时,一般情况下题目就会给出一个第二标尺,常见如下:

  1. 新增边权,以新增的边权代表花费为例,用cost[u][v]表示 U -> V 的花费,并新增一个数组c[],令从起点s到达u的最小花费为c[u],初始化时只有c[s]为0、其余均为INF。

当有两种或以上的最短路径时,一般情况下题目就会给出一个第二标尺,常见如下:

  1. 新增边权,以新增的边权代表花费为例,用cost[u][v]表示 U -> V 的花费,并新增一个数组c[],令从起点s到达u的最小花费为c[u],初始化时只有c[s]为0、其余均为INF。
for(int v = 0;v < n;v++){if(visit[v] == false && G[u][v] != INF){if(d[u] + G[u][v] < d[u]){d[v] = d[u] + G[u][v];cost[v] = c[u] + cost[u][v];}else if(d[u] + G[u][v] == d[u] && c[u] + cost[u][v] < c[v]){c[v] = c[u] + cost[u][v];}}}
  1. 新增点权,以新增的点权代表城市中能收集到的物资为例,用weight[u]表示城市 u 中的物资数目,并新增一个数组w[],令从起点s到达u的能收集的最大物资为w[u],初始化时只有w[s] = weight[s],其余均为0 。
for(int v = 0;v < n;v++){if(visit[v] == false && G[u][v] != INF){if(d[u] + G[u][v] < d[u]){d[v] = d[u] + G[u][v];w[v] = w[u] + weight[v];}else if(d[u] + G[u][v] == d[u] && c[u] + cost[u][v] < c[v]){w[v] = w[u] + weight[v];}}}
  1. 求最短路径条数,只需要增加一个数组num[],令起点s到达顶点u的最短路径条数为num[u],这样初始化时只有num[s] = 1、其余 num[s] 均为0 。
for(int j = 0;j < n;j++){if(visit[j] == false && G[u][j] != INF){if(dis[j] > dis[u] + G[u][j]){      //如果能找到更短的路径就更新 dis 数组dis[j] = dis[u] + G[u][j];           num[j] = num[u];}else if(dis[j] == dis[u] + G[u][j]){   //找到一条长度相等的路径num[j] += num[u];                   }}}

2.Bellman-Ford算法

  Dijkstra 算法可以很好的解决无负权图的最短路径问题,但如果出现了负边权,Dijkstra就会失效,为了更好地求解有负权的最短路径问题,需要使用Bellman-Ford算法,Bellman-Ford算法可以解决单源最短路径问题,但也能处理有负权边的情况。

#include <iostream>#include <vector>using namespace std;const int maxn = 500 + 5;const int INF = 1000000000;int dis[maxn];struct node{int v,d;//邻结点和邻接边的边权node(int v1,int d1):v(v1),d(d1) {}};int n,m;vector <node> Adj[maxn];bool Ford(int s){for(int i = 0;i < maxn;i++)dis[i] = INF;dis[s] = 0;for(int i = 0;i < n-1;i++){for(int u = 0;u < n;u++)for(int j = 0;j < Adj[u].size();j++){int v = Adj[u][j].v;//邻接边的顶点int d = Adj[u][j].d;//邻接边的边权if(dis[u] + d < dis[v]){dis[v] = dis[u] + d;}}}//以下为判断负环的代码for(int u = 0;u < n;u++)for(int j = 0;j < Adj[u].size();j++){int v = Adj[u][j].v;int d = Adj[u][j].d;if(dis[u] + d < dis[v]){//如果仍可以被松弛return false;           //说明图中有从源点可达的负环}}return true;}int main(void){int v1,v2,s,d;cin>>n>>m>>s;cin>>v1>>v2>>d;                 //负权值是单向的Adj[v1].push_back(node(v2,d));for(int i = 0;i < m-1;i++){cin>>v1>>v2>>d;Adj[v1].push_back(node(v2,d));Adj[v2].push_back(node(v1,d));}if(Ford(s)){cout<<"该图中没有负环。"<<endl;}else{cout<<"该图中存在负环。"<<endl;}for(int i = 0;i < n;i++)cout<<dis[i]<<" ";cout<<endl;return 0;}/*3 3 00 1 -30 2 11 2 53 3 00 1 -30 2 11 2 23 3 00 1 -30 2 11 2 1*/

3.SPFA算法

  SPFA算法是Bellman-Ford算法优化的结果

vector <node> Adj[maxn];bool SPFA(int s){for(int i = 0;i < maxn;i++)dis[i] = INF;dis[s] = 0;memset(num,0,sizeof(num);queue <int> q;q.push(s);visit[s] = true;num[s]++;while(!q.empty()){int u = q.front();q.pop();visit[u] = false;       //不在队列中for(int i = 0;i < Adj[u].size();i++){int v = Adj[u][i].v;//邻接边的顶点int d = Adj[u][i].d;//邻接边的边权//松弛操作if(dis[v] > dis[u] + d){dis[v] = dis[u] + d;if(!visit[v]){q.push(v);num[v]++;//当前结点入队次数加一visit[v] = true;if(num[v] >= n) return false;       //有可达的负环}}}}return true;}

4.Floyd算法

  Floyd 算法用来解决全源最短路径问题,即对给定的图G(V,E),求任意两点u,v之间的最短路径长度。

void Floyd(){for(int k = 0;k < n;k++)        //辅助顶点 k (一定要放在最外层)for(int i = 0;i < n;i++)for(int j = 0;j < n;j++){if(dis[i][k] != INF && dis[k][j] != INF){if(dis[i][j] > dis[i][k] + dis[k][j]){dis[i][j] = dis[i][k] + dis[k][j];}}}}

最短路径 的一些解法和特殊情况相关推荐

  1. 上海交大机试真题—最短路径(最小生成树解法)

    题目描述 N个城市,标号从0到N-1,M条道路,第K条道路(K从0开始)的长度为2^K,求编号为0的城市到其他城市的最短距离 输入描述: 第一行两个正整数N(2<=N<=100)M(M&l ...

  2. 图解弗洛伊德算法(每一对顶点之间的最短路径问题)

    文章目录 一.弗洛伊德算法概述 二.弗洛伊德算法的思想与步骤 2.1 基本思想 2.2 步骤图解说明 三.弗洛伊德算法的代码实现 一.弗洛伊德算法概述 在上一篇博客 图解迪杰斯特拉算法(最短路径问题) ...

  3. 15数字华容道解法 图解_数字华容道最后一行怎么解 最后一道解答技巧

    数字华容道的基本解法思路就如同魔方解法-样,下面开始教学步骤,先对第一排,将1.2.3一个个移到目标位置,这一步不需要什么技巧,只管将三个数字-个一个移就行,其它数字不用管. 在移数字4时先移到目标位 ...

  4. 单源最短路径-分支限界法-优先队列式分支限界法-Dijkstra

    问题描述: 给定一个带权有向图G = (V, E), 其中每条边的权是非负实数.另外,还给定V中的一个顶点,称为源.现在要计算源到所有其他各定点的最短长度.这里路的长度是指路上各边权之和.这个问题通常 ...

  5. c语言15-puzzle解法,15 Puzzle (4乘4谜题) IDA*(DFS策略与曼哈顿距离启发) 的C语言实现...

    大家好!这是我的第一篇博客,由于之前没有撰写博客的经验,并且也是初入计算机和人工智能领域,可能有些表述或者理解不当,还请大家多多指教. 一.撰写目的 由于这个学期在上算法与数据结构课程的时候,其中一个 ...

  6. postgis+geoserver最短路径

    postgis+geoserver最短路径 1 安装软件 2 数据预处理 3 操作postgres 4 操作Geoserver 5 计算最短路径 6 问题记录 1 安装软件 安装PostgreSQL与 ...

  7. 最短路径问题(Floyd算法、Dijkstra算法、Bellman-Ford算法、SPFA算法)

    导入 最短路径问题是指在一幅带权图中,找出连接两个顶点之间的所有路径中,边权和最短的那一条.如下图就是一幅带权图,边上的数字就代表该边的权值.解决最短路径问题有多种不同的算法,本文将对它们的基本思想与 ...

  8. 狄克斯特拉(Dijkstra)算法原理详细解释与实现(python)

    目录 写在前面 1. 简介 2. 原理 2.1 找出最便宜的节点 2.2 计算前往该节点的各个邻居的开销 2.3 重复上面的步骤 实现 总结 写在前面 本文原理摘自<算法图解>这本书. 其 ...

  9. 图论(三)--各种基础图算法总结

    图论总结 G=(V,E),V代表图中节点的合集,E代表图中边或是关系的合集. 稠密图:图中E的条数接近V*V也就是,接近任意两点之间相连. 稀疏图:图中E的条数远小于V*V. 图的数据结构 图常用的有 ...

最新文章

  1. android ArcGIS学习笔记一
  2. JavaFX 2.0示例介绍书
  3. 三包围结构的字是什么样的_拼音带kun的字大全_50个拼音含kun的字组词
  4. 修改支付宝账号的授权方式
  5. 音视频开发著作《Android音视频开发》终于发售了,先来一波签名送书福利!
  6. sap系统搭建教程_手把手安装SAP ERP系统
  7. C语言程序设计经典例题(考研必背)(基础篇)第二周
  8. wps里面函数怎么使用_WPS表格中常用文本函数的用法
  9. 【学习笔记之MYSQL篇】实体联系图
  10. C - Reverse Polish Calculator
  11. S32K144 CAN收发调试经验总结
  12. 【理解数据结构】队列的实现(C语言)
  13. luogu P2698 [USACO12MAR]花盆Flowerpot
  14. 新手必看:生成对抗网络的初学者入门指导
  15. 【元胞自动机】保守策略元胞自动机三车道(不开放辅路,软件园影响)交通流模型matlab源码
  16. 杜克计算机工程本科专业申请,Duke-C同学斩获2015 杜克大学 计算机工程硕士Offer一枚...
  17. 支付宝当面付-扫码支付
  18. RNA 25. SCI文章中只有生信没有实验该怎么办?
  19. SOEM协议栈代码研读笔记(二)
  20. 健世科技再次冲刺港股:年亏5亿 高瓴与春华资本是股东

热门文章

  1. 【java项目实践】具体解释Ajax工作原理以及实现异步验证username是否存在+源代码下载(java版)...
  2. Android启动Activity的两种方式与四种启动模式
  3. linux下echo命令详解(转)
  4. JSPatch – 动态更新iOS APP
  5. 修改VS2010生成的dll文件中的内容
  6. shell获取当前进程pid和上一个进程pid
  7. C#3.0语法新特性集合
  8. 海量数据库解决方案2011030401
  9. Asp.net高级程序设计之服务器控件(4)
  10. 基本电子电路系列——MOS管