Dijkstra
用一个数组存储一个确定的点到其他各个点的初始距离,并把这个点标记,然后在剩下的n-1个点中找到距离这个给定的点距离最短的点,然后把它标记后,用它当作中转点来松弛给定点到其他点的距离。一共找n-1次就可以了,因为一开始就把给定点标记了。
只适用于解决单源最短路径问题 不能解决负边权因为当扩展到一个负边时,已经更新过的两点之间的距离可能还会被修改掉,这就违背了这个算法已经更新的边为最小值的思想了。 适用于解决稠密图
洛谷P1339 [USACO09OCT] Heat Wave G
https://www.luogu.com.cn/problem/P1339
题目描述
有一个 𝑛*n* 个点 𝑚*m* 条边的无向图,请求出从 𝑠*s* 到 𝑡*t* 的最短路长度。
输入格式
第一行四个正整数 𝑛,𝑚,𝑠,𝑡*n*,*m*,*s*,*t*。 接下来 𝑚*m* 行,每行三个正整数 𝑢,𝑣,𝑤*u*,*v*,*w*,表示一条连接 𝑢,𝑣*u*,*v*,长为 𝑤*w* 的边。
输出格式
输出一行一个整数,表示答案。
package main
import (
"fmt"
"math"
)
var edge [2505][2505]int
var dis [2505]int
var book [2505]int
var n, m, s, t int
var inf = math.MaxInt/2 - 1
func dijkstra() {
for i := 1; i <= n; i++ {
dis[i] = edge[s][i]
}
//fmt.Println(dis[:20])
book[s] = 1
for i := 1; i <= n-1; i++ { //在循环开始前对1到1进行了确定,所以只需要进行n-1次循环就可以
var minn int = inf
var nextPos int = -1
for j := 1; j <= n; j++ {
if book[j] == 0 && dis[j] < minn {
nextPos = j
minn = dis[j]
}
}
if nextPos == -1 {
break
}
book[nextPos] = 1
for j := 1; j <= n; j++ {
if book[j] == 0 && dis[nextPos]+edge[nextPos][j] < dis[j] {
dis[j] = dis[nextPos] + edge[nextPos][j]
}
}
}
}
func main() {
fmt.Scan(&n, &m, &s, &t)
for i := 1; i <= n; i++ {
for j := 1; j <= n; j++ {
if i == j {
edge[i][j] = 0
} else {
edge[i][j] = inf
}
}
}
for i := 1; i <= m; i++ {
var u, v, w int
fmt.Scan(&u, &v, &w)
if w < edge[u][v] {
edge[u][v] = w
edge[v][u] = w
}
}
dijkstra()
fmt.Printf("%d\n", dis[t])
}
Bellman-Ford
遍历m条边,看是否能让从给定点直接到v点缩短为从给定点到u点再到v点。 因为任意两点之间的最短路径最多包含n-1条边,所以把这些边遍历n-1次就好。
适合解决单源最短路径
因为遍历的是m条边,和边密切相关,所以边数越小,计算越快,适合稀疏图 可以解决负边权,当第n次还能松弛时,说明存在负权回路
package main
import (
"fmt"
"math"
)
type Edge struct {
u, v, w int
}
var edge [6205]Edge
var dis [2505]int
var n, m, s, t int
var inf = math.MaxInt/2 - 1
func main() {
fmt.Scan(&n, &m, &s, &t)
for i := 1; i <= m; i++ {
fmt.Scan(&edge[i].u, &edge[i].v, &edge[i].w)
}
for i := 1; i <= n; i++ {
dis[i] = inf
}
dis[s] = 0 //以s为起点
for k := 1; k <= n-1; k++ { //把这些边遍历n-1次
var check = 0
for i := 1; i <= m; i++ {
if dis[edge[i].v] > dis[edge[i].u]+edge[i].w {
dis[edge[i].v] = dis[edge[i].u] + edge[i].w
check = 1
}
if dis[edge[i].u] > dis[edge[i].v]+edge[i].w {
dis[edge[i].u] = dis[edge[i].v] + edge[i].w
check = 1
}
}
if check == 0 {
break
}
}
/*
判断是否存在负权回路
var flag = 0
for i:=1; i<=m; i++{
if dis[edge[i].v] > dis[edge[i].u]+edge[i].w || dis[edge[i].u] > dis[edge[i].v]+edge[i].w{
flag = 1
break
}
}
if flag == 1{
//存在负权回路
}
*/
fmt.Printf("%d\n", dis[t])
}
SPFA+邻接表存图
https://blog.csdn.net/weixin_42172261/article/details/104174283