本文提纲
- 算法简介
- 算法思想
- 代码实现
- 反思与感悟
1.算法简介
Dijkstra算法,用于计算正权图上的单源最短路,即从单个源点出发,到所有结点的最短路。该算法适用于有向图和无向图,不能处理带有负权的图。
2. 算法思想
思想为单源点加入集合,更新dis[]数组,每次取dis[]最小的那个点,加入集合,再次更新dis[]数组,取点加入集合,直到所有的点都加入集合中
3.代码实现
以杭电2544题为例:
#include <stdio.h>
#include <string.h>
#define M 105
#define INF 0x3f3f3f3f
int map[M][M], low[M], n, m;
bool vis[M];
int dijstra(){
int ans = 0, pos, min, i, j;
//初始化数据
for(i = 2; i <= n; i ++){
//把和起点相连的顶点都加上权值
low[i] = map[1][i];
//标记都为0,表示都没有求到最短路径
vis[i] = 0;
}
//表示起点不用最短路径
vis[1] = 1;
low[1] = 0;
pos = 1;
//主循环,每次循环求得起点与一个顶点的最短路径
for(i = 2; i < n; i ++){
min = INF;
//找到一条最短路径
for(j = 2; j <= n; j ++){
if(!vis[j]&&low[j]<min){
min = low[j];
pos = j;
}
}
//
ans += min;
//将这个已经找到最短路径的节点标记为已遍历
vis[pos] = 1;
//通过已遍历的这个节点找到下一层节点,并更新low数组的值,相当于一次松弛操作
for(j = 2; j <= n; j ++){
if(!vis[j]&&low[j] > low[pos]+map[pos][j])
low[j] = low[pos]+map[pos][j];
}
}
return low[n];
}
int main(){
// freopen("test.txt","r",stdin);
// freopen("test.txt","w",stdout);
while(scanf("%d%d", &n, &m), n||m){
int i, j, a, b, c;
for(i = 0; i <= n; i ++){
for(j = 0; j <= n; j ++)
map[i][j] = INF;
}
for(i = 0; i < m; i ++){
scanf("%d%d%d", &a, &b, &c);
if(map[a][b] > c){
map[a][b] = map[b][a] = c;
}
}
printf("%d\n", dijstra());
}
// fclose(stdin);//关闭文件
// fclose(stdout);//关闭文件
return 0;
}
4.思想感悟
本次实现的Dijkstra算法还不是最优的,可以有队列进行优化,达到ElogV复杂度的最优算法。