最短路径算法(I)
弗洛伊德算法(Floyed-Warshall)
适用范围及时间复杂度
该算法的时间复杂度为O(N^3),适用于出现负边权的情况。
可以求取最短路径或判断路径是否连通。可用于求最小环,比较两点之间的大小。
(什么??你不知道什么是负边权??戳->http://t.cn/Ef7pbu6)
核心思想
对于任意一个K点,i到j的距离有两种可能:要么经过k点,要么不经过k点。所以我们只需要不断的迭代k,比较d[i][k]与d[i][k]+d[k][j]的值。如果后者更短,则更新d[i][k]的值。如此重复,最后检查完所有的k时,我们便得到了最短距离。
注意事项及常见问题
由核心思想不难看出,这个算法需要三层循环来实现。但k的位置是值得注意的。经过分析不难发现,k属于最外层循环。
i,j,k三点并不能相同。如若相同,则算法无意义。(自己到自己的距离当然是零啦)
在使用算法时,将map[i][j]值初始为最大/小,map[i][i]一定设置为0(自己到自己当然是零啦)
有时题目会暗含重复数据,也就是相同的路径权重不同。所以要根据题目进行数据比较,更新最大/小的值。
代码实现
初始化:如若两点(假定两点为u,v)相连,则其最短路径初始化为权重。如不相连则初始化为巨大值(0x7ffffff)
if(w[u][v]){
dis[u][v]=w[u][v];
}else{
dis[u][v]=*7ffffff;
}
戳开查看
step2:寻找中间点K,比较距离并判断是否更新。
for(int k=;k<=n;k++){
for(int i=;i<=n;i++){
for(int j=;j<=n;j++){
if(i!=k&&i!=j&&j!=k){
dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]);
}
}
}
}
戳开查看
迪杰斯特拉算法(dijkstra)
适用范围及时间复杂度
单源路径算法,只计算起点只有一个的情况。不可以用于处理存在负边权的情况。时间复杂度O(N^2)
多用于计算一个结点到其他所有结点的最短路径。以起始点为中心向外层扩展,直到扩展到终点为止。
核心思想
对于图中一个点G(V,E),可以被归为以下两组集合之一:
■白点集合:指已确定最短路径的顶点集合。用S表示,初始时S中只有一个元素,即源点,以后每求得一条最短路径,就加入到集合S中,直到全部顶点都加入S中,算法就结束了。
■蓝点集合:指未确定最短路径的顶点集合。用U表示,按最短路径长度的递增次序把第二组的顶点加入到S中。在加入过程中,总是寻找到与起点距离最短的先加入,保持集合S中的路径长度永远比集合U中的小。
用vis[v]标记顶点v是白点还是蓝点,白点用vis[v]=true标记,蓝点用vis[v]=false标记。很显然,初始化时,所有vis除源点为true外,其它均为false;
第1轮循环找到dis[1]最小,将1变成白点。对所有与之相连的蓝点做出改,使得:dis[2]=2;dis[3]=4;dis[4]=7;此时dis[2],dis[3],dis[4]被它最后一个中转点修改了最短路径。
第2轮循环找到dis[2]最小,将2变成白点。对所有与之相连的蓝点做出修改,使得:dis[3]=3;dis[5]=4;此时,dis[3],dis[5]被它最后一个中转点修改了最短路径
第3轮循环找到dis[3]最小,将3变为白点。对所有与之相连的蓝点做出修改,使得:dis[4]=4,而dis[5]之前已经计算出来等于4了,现在不能用9去修改。说明点3不是5的最后一个中转点。此时dis[4]被它最后一个中转点修改了最短路径。
第4轮循环找到dis[4]最小,将4变成白点。但点4没有与之相连的蓝点,故不需要做出修改。
第5轮循环找到dis[5]最小,把5置为白点,而已经没有与5相连接的蓝点。故无须更改。
如此过后,便得到了起点至各点的单源最短路径。
代码实现
我们至少需要三个数组来存储数据(邻接矩阵法)。暂定map[][]为邻接矩阵,s为起点,e为终点,dis[i]表示i点到源点的最短路径。bool vis[]表示该点为蓝点或白点。
初始化
for(int i=;i<=n;i++)
for(int j=;j<=n;j++) g[i][j]=maxx;
for(int i=;i<=n;i++) dis[i]=map[s][i]; //为dis赋初值
vis[s]=true; //起点标记为已访问
dis[s]=; //起点标记为白点
算法核心
for(int i=;i<=n-;i++){
minx=maxx;
for(int j=;j<=n;j++)
if(!vis[j]&&dis[j]<minx){
minx=dis[j]; //不断寻找dis的最小值,并把坐标保存在u中
u=j;
}
if(u==) break; //没找到蓝点,退出循环
vis[u]=true; //把找到的蓝点值为已访问
for(int v=;v<=n;v++)
//如果j到起点的最短路径大于k到起点的最短路径+k到j的距离,则更新dis[j]
dis[v]=min(dis[v],dis[v]+map[u][v]);
}
printf("%.2lf\n",dis[t]);
注意事项
dijskstra算法有两重循环,第一重循环是1到n-1,第二重循环是1到n。这中间可以优化的是,如果在接收数据的时候,保存最大的点p,这样,第一重循环就只需要扫描到p-1,而第二重循环只需要扫描到p。降低了时间复杂度。但多数时候,题目是给定了最大的点,不需要再找了。
for(int i=;i<=n;i++){
scanf("%d%d%d",&u,&v,&w);
if(g[u][v]>w) g[u][v]=g[v][u]=w;
p=max(p,max(u,v));
}
队列优化
priority_queue< pair<int,int> > q;
void Dijkstra()
{
memset(Distrance,0x3f,sizeof(Distrance));
Distrance[]=;
q.push(make_pair(,));
while(q.size())
{
int x=q.top().second;
q.pop();
if(Vist[x])
continue;
Vist[x]=true;
for(int i=Head[x]; i; i=Edges[i].Next)
{
int y=Edges[i].End;int z=Edges[i].Val;
if(Distrance[y]>Distrance[x]+z)
{
Distrance[y]=Distrance[x]+z;
q.push(make_pair(-Distrance[y],y));
}
}
}
}
最短路径算法(I)的更多相关文章
- Johnson 全源最短路径算法
解决单源最短路径问题(Single Source Shortest Paths Problem)的算法包括: Dijkstra 单源最短路径算法:时间复杂度为 O(E + VlogV),要求权值非负: ...
- Floyd-Warshall 全源最短路径算法
Floyd-Warshall 算法采用动态规划方案来解决在一个有向图 G = (V, E) 上每对顶点间的最短路径问题,即全源最短路径问题(All-Pairs Shortest Paths Probl ...
- Dijkstra 单源最短路径算法
Dijkstra 算法是一种用于计算带权有向图中单源最短路径(SSSP:Single-Source Shortest Path)的算法,由计算机科学家 Edsger Dijkstra 于 1956 年 ...
- Bellman-Ford 单源最短路径算法
Bellman-Ford 算法是一种用于计算带权有向图中单源最短路径(SSSP:Single-Source Shortest Path)的算法.该算法由 Richard Bellman 和 Leste ...
- 几大最短路径算法比较(Floyd & Dijkstra & Bellman-Ford & SPFA)
几个最短路径算法的比较:Floyd 求多源.无负权边(此处错误?应该可以有负权边)的最短路.用矩阵记录图.时效性较差,时间复杂度O(V^3). Floyd-Warshall算法(Floyd ...
- 带权图的最短路径算法(Dijkstra)实现
一,介绍 本文实现带权图的最短路径算法.给定图中一个顶点,求解该顶点到图中所有其他顶点的最短路径 以及 最短路径的长度.在决定写这篇文章之前,在网上找了很多关于Dijkstra算法实现,但大部分是不带 ...
- 无向图的最短路径算法JAVA实现
一,问题描述 给出一个无向图,指定无向图中某个顶点作为源点.求出图中所有顶点到源点的最短路径. 无向图的最短路径其实是源点到该顶点的最少边的数目. 本文假设图的信息保存在文件中,通过读取文件来构造图. ...
- 最短路径算法之Dijkstra算法(java实现)
前言 Dijkstra算法是最短路径算法中为人熟知的一种,是单起点全路径算法.该算法被称为是“贪心算法”的成功典范.本文接下来将尝试以最通俗的语言来介绍这个伟大的算法,并赋予java实现代码. 一.知 ...
- Floyd最短路径算法
看完这篇文章写的小程序,Floyd最短路径算法,求从一个点到另一个点的最短距离,中间可以经过其他任意个点.三个for循环,从i到j依次经过k的最短距离,最外层for循环是经过点K,内部两个循环是从i( ...
- 最短路径算法(Dijkstra算法、Floyd-Warshall算法)
最短路径算法具体的形式包括: 确定起点的最短路径问题:即已知起始结点,求最短路径的问题.适合使用Dijkstra算法. 确定终点的最短路径问题:即已知终结结点,求最短路径的问题.在无向图中,该问题与确 ...
随机推荐
- EF Core 2.1 Raw SQL Queries (转自MSDN)
Entity Framework Core allows you to drop down to raw SQL queries when working with a relational data ...
- printf重定向问题
1.使用printf库函数时,要加入头文件<stdio.h> 2.另外在keil里面需要把:use MicroLIB 勾选上,不然程序没办法在线调试.编译的时候不会报错. 3.当然可以不用 ...
- CSS 学习路线(二)选择器
选择器 规则结构: 分两个基本部分 选择器(selector)和声明块(declaration block) 组成 声明块:由一个或多个声明组成,每一个声明都是属性-值对 选择器分为:元素选择器,类选 ...
- SQL-还原数据库,数据库提示正在还原中的处理办法
还原数据库时,提示还原成功,可是数据库列表中该数据库显示正在还原中: 执行此命令即可: RESTORE DATABASE EnterPriseBuilding WITH RECOVERY 1. 至少有 ...
- EJB到底是什么?---通俗易懂,简单明了
EJB到底是什么? 1. 我们不禁要问,什么是"服务集群"?什么是"企业级开发"? 既然说了EJB 是为了"服务集群"和"企业 ...
- 使用 runtime 实现字符串转方法,并传递参数
利用runtime的动态机制实现字符串转方法并传递参数 使用 SEL 关键字引用方法声明,使用 methodForSelector 寻找方法实现, 使用函数指针调用方法. - (void)action ...
- TCP|UDP|Http|Socket
TCP_IP.Http.Socket的区别 - 计算机网络知识库 iOS-Socket网络通信-框架与API - 简书 CocoaAsyncSocket + Protobuf 处理粘包和拆包问题 - ...
- jQuery之scroll用法实例
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- 转:Sql Server中清空所有数据表中的记录
如果要删除数据表中所有数据只要遍历一下数据库再删除就可以了,清除所有数据我们可以使用搜索出所有表名,构造为一条SQL语句进行清除了,这里我一一给各位同学介绍. 使用sql删除数据库中所有表是不难的 ...
- ABAP术语-XML
XML 原文:http://www.cnblogs.com/qiangsheng/archive/2008/03/21/1115743.html The "eXtensible Markup ...