最短路径

最短路径算法

旧城冷巷雨未停 提交于 2020-01-19 15:21:07
Floyed算法 Floyed-Warshall 算法用来找出每对点之间的最短距离。它需要用邻接矩阵来储存边,这个算法通过考虑最佳子路径来得到最佳路径。 注意单独一条边的路径也不一定是最佳路径。 思想: 从任意一条单边路径开始。所有两点之间的距离是边的权,或者无穷大,如果两点之间没有边相连。 对于每一对顶点 u 和 v,看看是否存在一个顶点 w 使得从 u 到 w 再到 v 比己知的路径更短。如果是更新它。 特点: Floyed算法,是最简单的最短路径算法,可以计算图中任意两点间的最短路径。Floyed的时间复杂度是O (N3),适用于出现负边权的情况。 算法描述: 初始化:点u、v如果有边相连,则dis[u][v]=w[u][v]。 如果不相连则dis[u][v]=0x7fffffff for(int k=1;k<=n;k++) for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) if(dis[i][j]>dis[i][k]+dis[k][j]) dis[i][j]=dis[i][k]+dis[k][j]; 算法结束:dis[i][j]得出的就是从i到j的最短路径。 #include<iostream> using namespace std; const int maxn=9999999; int n,dis[101][101]; int x

一步步学算法(算法分析)---6(Floyd算法)

ぃ、小莉子 提交于 2020-01-19 15:20:38
Floyd 算法 Floyd 算法 又称为 弗洛伊德算法 ,插点法,是一种用于寻找给定的 加权图 中顶点间 最短路径 的算法。该 算法 名称以创始人之一、1978年图灵奖获得者、斯坦福大学计算机科学系教授 罗伯特·弗洛伊德 命名。 正如我们所知道的,Floyd算法用于求最短路径。Floyd算法可以说是Warshall算法的扩展,三个for循环就可以解决问题,所以它的时间复杂度为O(n^3)。 Floyd算法的基本思想如下:从任意节点A到任意节点B的最短路径不外乎2种可能,1是直接从A到B,2是从A经过若干个节点X到B。所以,我们假设Dis(AB)为节点A到节点B的最短路径的距离,对于每一个节点X,我们检查Dis(AX) + Dis(XB) < Dis(AB)是否成立,如果成立,证明从A到X再到B的路径比A直接到B的路径短,我们便设置Dis(AB) = Dis(AX) + Dis(XB),这样一来,当我们遍历完所有节点X,Dis(AB)中记录的便是A到B的最短路径的距离。 很简单吧,代码看起来可能像下面这样: for ( int i = 0; i < 节点个数; ++i ) { for ( int j = 0; j < 节点个数; ++j ) { for ( int k = 0; k < 节点个数; ++k ) { if ( Dis[i][k] + Dis[k][j] < Dis[i

Floyd算法

走远了吗. 提交于 2020-01-19 15:18:48
Floyd算法的基本思想如下:从任意节点A到任意节点B的最短路径不外乎2种可能,1是直接从A到B,2是从A经过若干个节点X到B。所以,我们假设Dis(AB)为节点A到节点B的最短路径的距离,对于每一个节点X,我们检查Dis(AX) + Dis(XB) < Dis(AB)是否成立,如果成立,证明从A到X再到B的路径比A直接到B的路径短,我们便设置Dis(AB) = Dis(AX) + Dis(XB),这样一来,当我们遍历完所有节点X,Dis(AB)中记录的便是A到B的最短路径的距离。 很简单吧,代码看起来可能像下面这样: ? for ( int i = 0; i < 节点个数; ++i ) { for ( int j = 0; j < 节点个数; ++j ) { for ( int k = 0; k < 节点个数; ++k ) { if ( Dis[i][k] + Dis[k][j] < Dis[i][j] ) { // 找到更短路径 Dis[i][j] = Dis[i][k] + Dis[k][j]; } } } } 但是这里我们要注意循环的嵌套顺序,如果把检查所有节点X放在最内层,那么结果将是不正确的,为什么呢?因为这样便过早的把i到j的最短路径确定下来了,而当后面存在更短的路径时,已经不再会更新了。 让我们来看一个例子,看下图: 图中红色的数字代表边的权重

SPFA算法——最短路径

感情迁移 提交于 2020-01-19 15:18:04
粗略讲讲SPFA算法的原理,SPFA算法是1994年西安交通大学段凡丁提出 是一种求单源最短路的算法 算法中需要用到的主要变量 int n; //表示n个点,从1到n标号 int s,t; //s为源点,t为终点 int d[N]; //d[i]表示源点s到点i的最短路 int p[N]; //记录路径(或者说记录前驱) queue <int> q; //一个队列,用STL实现,当然可有手打队列,无所谓 bool vis[N]; //vis[i]=1表示点i在队列中 vis[i]=0表示不在队列中 几乎所有的最短路算法其步骤都可以分为两步 1.初始化 2.松弛操作 初始化: d数组全部赋值为INF(无穷大);p数组全部赋值为s(即源点),或者赋值为-1,表示还没有知道前驱 然后d[s]=0; 表示源点不用求最短路径,或者说最短路就是0。 将源点入队;     (另外记住在整个算法中有顶点入队了要记得标记vis数组,有顶点出队了记得消除那个标记) 队列+松弛操作 读取队头顶点u,并将队头顶点u出队(记得消除标记);将与点u相连的所有点v进行松弛操作,如果能更新估计值(即令d[v]变小),那么就更新,另外,如果点v没有在队列中,那么要将点v入队(记得标记),如果已经在队列中了,那么就不用入队 以此循环,直到队空为止就完成了单源最短路的求解 SPFA可以处理负权边 定理:

Floyd算法

混江龙づ霸主 提交于 2020-01-19 15:17:49
  Floyd算法的基本思想如下:从任意节点A到任意节点B的最短路径不外乎2种可能,1是直接从A到B,2是从A经过若干个节点X到B。所以,我们假设Dis(AB)为节点A到节点B的最短路径的距离,对于每一个节点X,我们检查Dis(AX) + Dis(XB) < Dis(AB)是否成立,如果成立,证明从A到X再到B的路径比A直接到B的路径短,我们便设置Dis(AB) = Dis(AX) + Dis(XB),这样一来,当我们遍历完所有节点X,Dis(AB)中记录的便是A到B的最短路径的距离。 代码如下: for ( int i = 0; i < 节点个数; ++i ) { for ( int j = 0; j < 节点个数; ++j ) { for ( int k = 0; k < 节点个数; ++k ) { if ( Dis[i][k] + Dis[k][j] < Dis[i][j] ) { // 找到更短路径 Dis[i][j] = Dis[i][k] + Dis[k][j]; } } } } 但是这里我们要注意循环的嵌套顺序,如果把检查所有节点X放在最内层,那么结果将是不正确的,为什么呢?因为这样便过早的把i到j的最短路径确定下来了,而当后面存在更短的路径时,已经不再会更新了。 让我们来看一个例子,看下图: 图中红色的数字代表边的权重。如果我们在最内层检查所有节点X,那么对于A-

5.5最短路径F+D

扶醉桌前 提交于 2020-01-19 00:35:33
//Floyd 算法 # include <stdio.h> # include <math.h> struct edge { int a , b ; //下一节点的编号 int cost ; //该边的权重 } edge [ 6000 ] ; int ans [ 101 ] [ 101 ] ; //邻接矩阵 int main ( ) { int n , m ; //商店数 路数 int a , b , cost ; while ( scanf ( "%d%d" , & n , & m ) != EOF && ( n != 0 || m != 0 ) ) { for ( int i = 1 ; i <= n ; i ++ ) for ( int j = 1 ; j <= n ; j ++ ) { if ( i != j ) ans [ i ] [ j ] = - 1 ; //邻接矩阵初始化 ,-1代表无穷 ans [ i ] [ j ] = 0 ; //自己到自己为0 } for ( int i = 1 ; i <= m ; i ++ ) { //把各路权值输入 scanf ( "%d%d%d" , & a , & b , & cost ) ; ans [ a ] [ b ] = ans [ b ] [ a ] = cost ; //生成以a,b为点,以cost为权值的边 !a-

Johnson's Algorithm for ASPS(All Pairs Shortest Path)

爱⌒轻易说出口 提交于 2020-01-19 00:18:23
之前由于觉得博客写起来没有笔记方便,所以停了很久。 最近开始使用markdown来写博客,感觉挺清爽,又要开始增产啦~ Johnson's Algorithm = Bellman-Ford + Dijkstra 若是仅仅使用|V|次Dijkstra算法跑完全图可以求得最短路径,时间复杂度(V2log|V| + VE) 虽然效率比Floyd高,但是只能处理正权图 Johnson算法就是将所有边预处理重新赋值,使全部边权为正,再利用Dijkstra处理 注意:不能单纯地每条边加上某个权值w,这样会改变最短路径 Example: s --> t 1 1 1 s ------ a ----- b ----- t \____________________/ 4 初始最短路,s-->a-->b-->t 若全部边同时+1,最短路变成s-->t 所以不能以边为单位来进行权值相加,应以**路径**为单位进行边的相加 Johnson算法Bellman-Ford预处理: 赋予每个顶点权值h[v] 对于边e(u,v),reweight之后的边权 = w(u,v) + h[u] - h[v] 那么对于u,v之间的任意路径增加的总权值是一样的(h[t]-h[s]),且每条边的边权>=0 获得h[i]的预处理步骤: 新建一个辅助点k, k与所有图中的点相连 从k到原图中各点i的最短距离就是h[i]

最短路径

戏子无情 提交于 2020-01-17 02:29:59
要求最短的路径,首先得把这些边都存储起来,边的存储有邻接表和邻接矩阵两种,这个题数据最大20万个,用邻接矩阵肯定不行,只能使用邻接表来存储。 求最短路的算法 Dijkstra,Floyd,Bellman,spfa; 这个题想要100%通过测试用例,只能使用效率高但是不是很稳定的spfa算法。 需要注意的是,初始化给所有路径的长度定义的无穷大这个数值,不能太大,也不能太小,比如说0x3fffffff,具体大小根据题中所给的边权的范围来定。 Dijkstra(迪杰斯特拉)算法 Dijkstra算法所求的是单源的最短路径,从起点开始,每一次都找到当前起点的最短可到达的点,然后再进行松弛。 该算法在使用时要求所包括的边中不能有负权边。 这可以看出,原本A -> B最短路径应该是 1 ,如果存在负权边的话就变成了2 # define MAXN 1000 //最大顶点数 # define INF 0x3fffffff //一个很大的数 int n = 0 , m = 0 , s = 0 ; //n为顶点数 m为边数 s为起点 int d [ MAXN ] = { 0 } ; //起点到各点最短路径的长度 int visit [ MAXN ] = { 0 } ; //记录已经找到的最短路径的点 0--》未找到 1--》表示找到 int arr [ MAXN ] [ MAXN ] = { 0 }

最短路径问题【Bellman-Ford】

流过昼夜 提交于 2020-01-16 18:58:34
Time Limit:10000MS Memory Limit:65536K Total Submit:619 Accepted:330 Case Time Limit:1000MS Description 平面上有 n n n 个点 ( N < = 100 ) (N<=100) ( N < = 1 0 0 ) ,每个点的坐标均在 − 10000 10000 -10000~10000 − 1 0 0 0 0 1 0 0 0 0 之间。其中的一些点之间有连线。若有连线,则表示可从一个点到达另一个点,即两点间有通路,通路的距离为两点直线的距离。现在的任务是找出从一点到另一点之间的最短路径。 Input 输入文件 s h o r t . i n short.in s h o r t . i n ,共有 n + m + 3 n+m+3 n + m + 3 行,其中: 第一行为一个整数 n n n 。 第 2 2 2 行到第 n + 1 n+1 n + 1 行(共 n n n 行),每行的两个整数 x x x 和 y y y ,描述一个点的坐标(以一个空格隔开)。 第 n + 2 n+2 n + 2 行为一个整数 m m m ,表示图中的连线个数。 此后的 m m m 行,每行描述一条连线,由两个整数 I , j I,j I , j 组成,表示第 i i i 个点和第 j j j

【图论】【最短路】最短路径问题

谁说胖子不能爱 提交于 2020-01-16 10:51:56
Description 平面上有n个点(N<=100),每个点的坐标均在-10000~10000之间。其中的一些点之间有连线。若有连线,则表示可从一个点到达另一个点,即两点间有通路,通路的距离为两点直线的距离。现在的任务是找出从一点到另一点之间的最短路径。 Input 输入文件short.in,共有n+m+3行,其中: 第一行为一个整数n。 第2行到第n+1行(共n行),每行的两个整数x和y,描述一个点的坐标(以一个空格隔开)。 第n+2行为一个整数m,表示图中的连线个数。 此后的m行,每行描述一条连线,由两个整数I,j组成,表示第i个点和第j个点之间有连线。 最后一行:两个整数s和t,分别表示源点和目标点。 Output 输出文件short.out仅一行,一个实数(保留两位小数),表示从S到T的最短路径的长度。 Sample Input 5 0 0 2 0 2 2 0 2 3 1 5 1 2 1 3 1 4 2 5 3 5 1 5 Sample Output 3.41 解题思路 最短路模板,输入的时候需要用公式 求出两个连接的点的距离(边权) Ford算法 未更新的为蓝点,更新过的为白点 d i s [ 1 dis[1 d i s [ 1 ~ 5 ] = ∞ 5]=∞ 5 ] = ∞ 从 1 1 1 出发, 1 1 1 标记为白点 d i s [ 1 ] = 0 , d i s