- 1、本文档共45页,可阅读全部内容。
- 2、原创力文档(book118)网站文档一经付费(服务费),不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。
- 3、本站所有内容均由合作方或网友上传,本站不对文档的完整性、权威性及其观点立场正确性做任何保证或承诺!文档内容仅供研究参考,付费前请自行鉴别。如您付费,意味着您自己接受本站规则且自行承担风险,本站不退款、不进行额外附加服务;查看《如何避免下载的几个坑》。如果您已付费下载过本站文档,您可以点击 这里二次下载。
- 4、如文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“版权申诉”(推荐),也可以打举报电话:400-050-0827(电话支持时间:9:00-18:30)。
查看更多
第四章 第三节 最短路径算法 如下图所示,我们把边带有权值的图称为带权图。边的权值可以理解为两点之间的距离。一张图中任意两点间会有不同的路径相连。最短路径就是指连接两点的这些路径中最短的一条。 我们有四种算法可以有效地解决最短路径问题。有一点需要读者特别注意:边的权值可以为负。当出现负边权时,有些算法不适用。 一、求出最短路径的长度 以下没有特别说明的话,dis[u][v]表示从u到v最短路径长度,w[u][v]表示连接u,v的边的长度。 1.Floyd-Warshall算法 O(N3) 简称Floyd(弗洛伊德)算法,是最简单的最短路径算法,可以计算图中任意两点间的最短路径。Floyd的时间复杂度是O (N3),适用于出现负边权的情况。 算法描述: 初始化:点u、v如果有边相连,则dis[u][v]=w[u][v]。 如果不相连则dis[u][v]=0x7fffffff For (k = 1; k = n; k++) For (i = 1; i = n; i++) For (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的最短路径。 算法分析思想讲解: 三层循环,第一层循环中间点k,第二第三层循环起点终点i、j,算法的思想很容易理解:如果点i到点k的距离加上点k到点j的距离小于原先点i到点j的距离,那么就用这个更短的路径长度来更新原先点i到点j的距离。 在上图中,因为dis[1][3]+dis[3][2]dis[1][2],所以就用dis[1][3]+dis[3][2]来更新原先1到2的距离。 我们在初始化时,把不相连的点之间的距离设为一个很大的数,不妨可以看作这两点相隔很远很远,如果两者之间有最短路径的话,就会更新成最短路径的长度。Floyd算法的时间复杂度是O(N3)。 Floyd算法变形: 如果是一个没有边权的图,把相连的两点间的距离设为dis[i][j]=true,不相连的两点设为dis[i][j]=false,用Floyd算法的变形: For (k = 1; k = n; k++) For (i = 1; i = n; i++) For (j = 1; j = n; j++) dis[i][j] = dis[i][j] || (dis[i][k] dis[k][j]); 用这个办法可以判断一张图中的两点是否相连。 最后再强调一点:用来循环中间点的变量k必须放在最外面一层循环。 【例4-1】、最短路径问题 【问题描述】 平面上有n个点(n=100),每个点的坐标均在-10000~10000之间。其中的一些点之间有连线。 若有连线,则表示可从一个点到达另一个点,即两点间有通路,通路的距离为两点间的直线距离。现在的 任务是找出从一点到另一点之间的最短路径。 【输入格式】 输入文件为short.in,共n+m+3行,其中: 第一行为整数n。 第2行到第n+1行(共n行) ,每行两个整数x和y,描述了一个点的坐标。 第n+2行为一个整数m,表示图中连线的个数。 此后的m 行,每行描述一条连线,由两个整数i和j组成,表示第i个点和第j个点之间有连线。 最后一行:两个整数s和t,分别表示源点和目标点。 【输出格式】 输出文件为short.out,仅一行,一个实数(保留两位小数),表示从s到t的最短路径长度。 【参考程序】 #includecstdio #includeiostream #includecmath #includecstring using namespace std; int a[101][3]; double f[101][101]; int n,i,j,k,x,y,m,s,e; int main() { freopen(short.in,r,stdin); freopen(short.out,w,stdout); cin n; for (i = 1; i = n; i++) cin a[i][1] a[i][2]; cin m; memset(f,0x7f,sizeof(f)); //初始化f数组为最大值 for (i = 1; i = m; i++)
文档评论(0)