单源最短路径 --Dijkstra算法-通过边实现松弛
2016-04-27 19:07
302 查看
单源最短路径 --Dijkstra算法-通过边实现松弛
算法思想:
每次找到离源点最近的一个顶点,然后以该顶点为中心进行扩展,最终得到源点到其余所有点的最短路径
基本步骤如下:
1、将所有的顶点分为两部分:已知最短路程的顶点集合P和未知最短路径的顶点集合Q。最开始,已知最短路径的顶点集合P中只有源点一个顶点,我们这里用一个 book数组来记录哪些点在集合P中。例如对于某个顶点i,如果book[i]为1,则表示这个顶点在集合P中,如果book[i]为0则表示这个顶点在集合Q中。
2、设置源点s到自己的最短路径的为0,即dis[s]=0;若存在有源点能直接到达的顶点i,则把dis[i]设置为e[s][i]。同时把所有其他(源点不能直接到达的)顶点的最短路径设为正无穷。
3、在集合Q中的所有顶点中选择一个离源点s最近的顶点u(即dis[u]最小)加入到集合P。并考察所有以u为起点的边,对每一条边进行松弛操作。例如存在一条从u到v的边,那么可以通过将边u->v添加到尾部来拓展一条从s到v的路径,这条路径的长度是dis[u]+e[u][v]。如果这个值比目前已知的dis[v]的值要小,我们可以用新值来代替当前的dis[v]中的值。
4、重复第3步,如果集合Q为空,算法结束。最终dis数组中的值就是源点到所有的顶点的最短路径。
例如:
求顶点1到其他顶点的距离
第一行输入两个整数n和m。n表示顶点个数(编号1到n),
m表示边的条数。接下来m行,每行有3个数,
xyz,表示顶点x到顶点y边的权值为z。
input
6 9
1 2 1
1 3 12
2 3 9
2 4 3
3 5 5
4 3 4
4 5 13
4 6 15
5 6 4
output
0 1 8 4 13 17
算法思想:
每次找到离源点最近的一个顶点,然后以该顶点为中心进行扩展,最终得到源点到其余所有点的最短路径
基本步骤如下:
1、将所有的顶点分为两部分:已知最短路程的顶点集合P和未知最短路径的顶点集合Q。最开始,已知最短路径的顶点集合P中只有源点一个顶点,我们这里用一个 book数组来记录哪些点在集合P中。例如对于某个顶点i,如果book[i]为1,则表示这个顶点在集合P中,如果book[i]为0则表示这个顶点在集合Q中。
2、设置源点s到自己的最短路径的为0,即dis[s]=0;若存在有源点能直接到达的顶点i,则把dis[i]设置为e[s][i]。同时把所有其他(源点不能直接到达的)顶点的最短路径设为正无穷。
3、在集合Q中的所有顶点中选择一个离源点s最近的顶点u(即dis[u]最小)加入到集合P。并考察所有以u为起点的边,对每一条边进行松弛操作。例如存在一条从u到v的边,那么可以通过将边u->v添加到尾部来拓展一条从s到v的路径,这条路径的长度是dis[u]+e[u][v]。如果这个值比目前已知的dis[v]的值要小,我们可以用新值来代替当前的dis[v]中的值。
4、重复第3步,如果集合Q为空,算法结束。最终dis数组中的值就是源点到所有的顶点的最短路径。
例如:
求顶点1到其他顶点的距离
第一行输入两个整数n和m。n表示顶点个数(编号1到n),
m表示边的条数。接下来m行,每行有3个数,
xyz,表示顶点x到顶点y边的权值为z。
input
6 9
1 2 1
1 3 12
2 3 9
2 4 3
3 5 5
4 3 4
4 5 13
4 6 15
5 6 4
output
0 1 8 4 13 17
#include<stdio.h> int main(void) { int e[10][ 10],dis[10],book[10]; int i,j,n,m,t1,t2,t3; int u,v,min; int inf=99999999; scanf("%d %d",&n,&m); for(i=1;i<=n;i++) { for(j=1;j<=n;j++) { if(i==j) { e[i][j]=0; } else { e[i][j]=inf; } } } for(i=1;i<=m;i++) { scanf("%d %d %d",&t1,&t2,&t3); e[t1][t2]=t3; } for(i=1;i<=n;i++) { dis[i]=e[1][i]; } for(i=1;i<=n;i++) { book[i]=0; } book[1]=1; //Dijkstra算法核心语句 for(i=1;i<=n-1;i++) { min=inf; for(j=1;j<=n;j++) { if(book[j]==0&&dis[j]<min) { min=dis[j]; u=j; } } book[u]=1; for(v=1;v<=n;v++) { if(e[u][v]<inf) { if(dis[v]>dis[u]+e[u][v]) { dis[v]=dis[u]+e[u][v]; } } } } for(i=1;i<=n;i++) { printf("%d ",dis[i]); } printf("\n"); return 0; }
相关文章推荐
- Zabbix利用msmtp+mutt发送邮件报警
- nyoj 45棋盘覆盖
- BZOJ 4517: [Sdoi2016]排列计数 错排公式
- Groovy入门教程
- 大规模密集型网络
- hdoj2007(java)平方和与立方和
- Qt5音乐播放器
- C++随机崩溃捕捉处理
- linux命令之git
- android蓝牙测试
- code vs 1090 加分二叉树 (树形DP)
- LeetCode *** 344. Reverse String
- JVM - 堆外内存
- Android集成Fresco框架导致在64位机器上(三星S6,华为P8等)找不到其他so库
- 改变UITableViewCell删除状态时,改变按钮的背景颜色。
- 写连接代码时需要注意2000和2005的不同:
- 人工智能大拿解答机器学习30个问答
- PHP 使用json_encode 解析数据库查询结果, 得到 json 最外层有中括号 [ ]
- mac 端口被占用及kill端口
- 编写高质量iOS代码与OS X代码的effective 方法小结