数据结构/图论:最小路径问题

一、问题描述及分类

最短路问题( short- path problem)是指若网络中的每条边都有一个数(权)值(长度、成本、时间等),则找出两节点之间总权值和最小的路径就是最短路问题。
●最短路径问题的分类:
已知全局信息的最短路径问题
已知局部信息的最短路径问题
●最短路径问题的分类:
无权图中最短路径
有权图中的最短路径
含有负边的有权图中的最短路径
●最短路径问题的分类:
单源最短路径
全局最短路径
两点最短路径

二、算法实现

1、Dijkstra算法

解决问题类型:单源最短路径问题
算法思想:最短路径的子路径仍然是最短路径。为了求出最短路径,该算法是以最短路径长度递增,逐次生成最短路径。
(1)路径长度最短的最短路径的特点:
在这条路径上,必定只含一条弧,并且这条弧的权值最小。
(2)下一条路径长度次短的最短路径的特点:
它只可能有两种情况:或者是直接从源点到该点(只含一条弧);或者是 从源点经过顶点v1,再到达该顶点(由两条弧组成)。
(3)再下一条路径长度次短的最短路径的特点:
它可能有三种情况:或者是直接从源点到该点(只含一条弧);或者是从源点经过顶点V1,再到达该顶点(由两条弧组成);或者是从源点经过顶点v2,再到达该顶点。
(4)其余最短路径的特点:
它或者是直接从源点到该点(只含一条弧);或者是从源点经过已求得最短路径的顶点。再到达该顶点。

伪代码实现:

// Compute shortest path distances from s,
// return them in D
void Dijkstra(Graph* G,int* D,int s)
{//对图G求从s出发到其他顶点的最短距离int i,v,w;for(i=0;i<G->n();i++){ // Do verticesv=minVertex(G,D);// 取目前未访问的距离最短的顶点if(D[v]==INFINITY) return;//不可达顶点G->setMark(v,VISITED);//加入S集合for (w=G->first(v);w<G->n();w= G->next(v,w))if(D[w]>(D[v]+G->weight(v,w)))D[w]=D[v]+G->weight(v,w);//若从源至W的路径经过V的距离更短,则更新最短距离}
}

minVertex函数:

// Find min cost vertex寻找未访问的最短距离顶点
int minVertex(Graph* G,int* D)
{int i,V;// Set v to an unvisited vertexfor(i=0;i<G->n();i++)if(G->getMark(i)==UNVISITED){v=i;break;}// Now find smallest D va luefor(i++;i<G->n0;i++)if((G->getMark(i)==UNVISITED)&&(i<D[v1]))v=i;return V;
}

优先队列实现的算法:

void Dijkstra(Graph* G, int* D, ints)
{int i, v, w;// v is current vertexDijkElem temp;DijkElem E[G->e0]; // Heap arraytemp.distance=0;temp.vertex=s;E[0]=temp; // Initialize heap arrayminheap<DijkElem,DDComp> H(E,1,G->e0);for(i=0;i<G->n();i++){// Get distancesdo{if(H.size()==0) return;//无数据可删除temp=H.removefirst();//取出第一一个元素,即最短距离V=temp.vertex;} while(G->getMark(v)==VISITED);G->setMark(v,VISITED);if(D[v]==INFINITY) return;//不可达顶点for(w=G->first(V);w<G->n();w=G->next(v,w))if (D[w]>(D[v]+G->weight(v, w)){// 更新DD[w]=D[v]+G->weight(v,w);temp.distance=D[w];temp.vertex=w;H.insert(temp); // Insert in heap}
}

注意:Djkstra算法只适合非负权值的图。

2、Bellman-Ford算法

解决问题类型:单源最短路径问题
算法思想:构造一个最短路径长度数组 序列dist1 [u],dist2 [u],…,dist n-1 [u]。其中, dist1 [u]是从源点v到终点u的只经过一条边的最 短路径的长度,dist1 [u] = Edge[v][u];dist2 [u] 是从源点v最多经过两条边到达终点u的最短路 径的长度,dist3 [u]是从源点v出发最多经过不构 成带负长度边回路的三条边到达终点u的最短路 径的长度,…,dist n-1 [u]是从源点v出发最多经过不构成带负长度边回路的n-1条边到达终点u 的最短路径的长度。
设已经求出distk1[i],j=0, 1,…n-1,此即从源点v最多经过不构成带负长度边回路的k-1条边到达终点j的最短路径的长度。
从图的邻接矩阵中可以找到各个顶点j到达顶点u的距离Edge[j][u],计算min {dist k-1 [j] + Edge[j][u]},可得从源点v绕过各个顶点,最多经过不构成带负长度边回路的k条边到达终点u的最短路径的长度。
用它与dist k-1 [u]比较,取小者作为dist k [u]的值。

伪代码实现:

void Graph::BellmanFord ( const int n, const int v )
{//在带权有向图中有的边具有负的权值。从顶点V找到所有其它顶点的最短路径for( int i=0;i<n;i++ ){dist[i]=Edge[v][i];if(i!=v&&dist[i]<MAXINT)path[i]=V;else path[i]=-1;}for(int k=2;k<n;k++)for(int u=0;u<n;u++)if(u!=v)for(i=0;i<n;i++ )if(Edge[i][u]>0 && Edge[i][u]<MAXINT && dist[u]>dist[i]+Edge[i][u]){dist[u]=dist[i]+Edge[i][u];path[u]=i;}
}

注意:Bellman-Ford算法适合负权值的图。

3、Floyd 算法

解决问题类型:全源最短路径问题
算法思想:
(1)定义k-path为任意一条 从顶点v到u的,中间顶点序号小于k的路径。 0-path即为直接地从v到u的边。
(2)定义Dk(v, u)为从v到u的最小的k-path的长度
(3)假设已知从v到u的最短k-path path,则最短的(k+1)-path经过,或不经过顶点k :
如果它经过顶点k,则最短(k+1)-path 的一部分是从v到k的最短k-path,另一部分是从k到u的最短k-path。
否则,保持其值为最短k-path不变。

伪代码实现:

//Floyd's all-pairs shortest paths algorithm
void Floyd(Graph* G)
{int D[G->n()][G->n()]; // Store distancesfor(int i=0;i<G->n();i++) // Initializefor(int j=0;j<G->n();j++)D[i][j]=G->weight(i,j); // Compute all k pathsfor(int k=0;k<G->n();k++)for(int i=0;i<G->n();i++)for(int j=0;j<G->n();j++)if(D[i][j]>(D[i][k]+D[k][j]))D[i][j]=D[i][k]+D[k][j];
}

注意:Floyd算法也适合负权值的图。

数据结构/图论:最小路径问题相关推荐

  1. ssl1341-最小路径覆盖【最大匹配,最小路径覆盖,图论】

    正题 大意 给一个无向图,求最少需要多少条路径可以连接所有点. 解题思路 一个公式就好了 最小路径覆盖数=最大匹配数 代码 #include<cstdio> #include<cst ...

  2. 【POJ - 2594】Treasure Exploration(floyd传递闭包 + 最小路径覆盖,图论)

    题干: Have you ever read any book about treasure exploration? Have you ever see any film about treasur ...

  3. 【每日算法】【图论】【最小边覆盖 最小路径覆盖 最小顶点覆盖 最大独立集 最大团】

    最小边覆盖 = 最大独立集 = |V| - 最大匹配数 这个是在原图是二分图上进行的 最小路径覆盖和最小边覆盖不同,不要求给的图是二分图,而是要求是N x N的有向图,不能有环,然后根据原图构造二分图 ...

  4. 最大匹配、最小顶点覆盖、最大独立集、最小路径覆盖(转)

    在讲述这两个算法之前,首先有几个概念需要明白: 二分图:  二分图又称二部图,是图论中的一种特殊模型.设G=(V,E)是一个无向图,如果顶点V可以分割为两个互不相交的子集(A,B),并且图中的每条边( ...

  5. 最大流 ---- 最小路径覆盖 ---- P2765魔术球问题(网络流24题)

    题目链接 解题思路: 这题题目看起来根本不像网络流但是确实用网络流做的 这个题目有两个限制 每个柱子上面的球相邻两个的和必须是平方数 球的编号必须是连续的 首先我们只考虑第一个条件的话,我们怎么转化成 ...

  6. 【网络流24题】D、魔术球问题(有向无环图的最小路径覆盖、思维)

    D.魔术球问题(有向无环图的最小路径覆盖.思维)[省选/NOI- ] P2765 魔术球问题 [问题分析] 枚举答案转化为判定性问题,然后最小路径覆盖,可以转化成二分图最大匹配,从而用最大流解决. [ ...

  7. 三角形最小路径和(动态规划)

    原创公众号:bigsai 欢迎加入力扣打卡 文章已收录在 全网都在关注的数据结构与算法学习仓库 欢迎star 题目描述 力扣120原题 给定一个三角形 triangle ,找出自顶向下的最小路径和. ...

  8. LeetCode 64最小路径和65有效数字66加一

    原创公众号:bigsai 专注于Java.数据结构与算法,一起进大厂不迷路! 关注后回复进群即可加入力扣打卡群,欢迎划水.近期打卡: LeetCode打卡 52八皇后Ⅱ&53最大子序和& ...

  9. Acwing.379 捉迷藏(最小路径重复点覆盖)

    传送门 1.前置知识 1.最小路径点覆盖 DAG中选出最小数量的不相交路径(无公共点),将所有点覆盖. 求法:将DAG中的点拆成出点和入点,构成一个二分图. 则原图的最小路径点覆盖转化到新图中: 1. ...

  10. 【网络流24题】最小路径覆盖问题

    [题目]1738: 最小路径覆盖问题 [题解]网络流 关于输出路径,因为即使有反向弧经过左侧点也一定会改变左侧点的去向,若没连向右侧就会被更新到0,所以不用在意. mark记录有入度的右侧点,然后从没 ...

最新文章

  1. c 找文件服务器文件,Linux C/C++项目:虚拟文件服务器(功能匹配百度网盘)
  2. 从ubuntu中文论坛转载的一片超好的文章,慢慢学习中
  3. java 线程池 源码_java线程池源码分析
  4. 动态规划立体匹配代码_411,动态规划和递归求不同路径 II
  5. vue 如何获取图片的原图尺寸_公众号封面图片尺寸是多少?如何在公众号里制作封面图?...
  6. [Swift实际操作]七、常见概念-(13)使用UIScreen查询设备屏幕信息
  7. mac系统虚拟机上的Linux系统的使用说明
  8. armbian安装图形桌面_archlinux / parabola 图形用户界面安装教程
  9. Redis 4.0深入持久化
  10. HttpUtility.UrlEncode、HttpUtility.UrlDecode、Server.UrlEncode、Server.UrlDecode的区分与应用
  11. 软件测试工作总结(二)
  12. 百度地图点聚合开发-地图找房功能
  13. dataFrame(DF)将数据插入ES时报错 org.elasticsearch.hadoop.EsHadoopIllegalArgumentException: Cannot detect E
  14. 页面性能优化办法有哪些?
  15. html 整个页面淡入浅出,css3网页的淡入淡出效果
  16. 支付宝小程序-实名认证流程讲解
  17. 使用python Telegram 机器人推送消息
  18. Jmeter的Html报告汉化及解析
  19. 与小雷粉-半初夏的聊天感悟
  20. 测试类型-- 按测试对象分 ※

热门文章

  1. 制作单机俄罗斯方块游戏总结(一)
  2. 不显示藏宝阁试穿服务器,梦幻西游:藏宝阁试穿功能的妙用,无限回档测试
  3. android通用对话框,android-所有活动中的“通用”对话框
  4. 华为5ipro详细参数使用功能_华为nova6se和nova5ipro的参数配置对比评价
  5. 差点被开除:一次订单号重复的事故
  6. 10年腾讯技术专家有话对你说
  7. kitti数据集_CVPR2020 | PV-RCNN: 3D目标检测 Waymo挑战赛+KITTI榜 单模态第一算法
  8. many to many mysql_mysql “Too many connections” 解决办法
  9. python编码在哪里看_python怎么换编码
  10. 2020服务器虚拟化市场容量,2020年服务器市场的五大技术和市场趋势