ACM入门题-力扣tusimple-005. 服务器-图论最短路径Go语言
tusimple-005. 服务器 中等
描述
公司来了一批新的分布式服务器,TuTu 要负责启动他们。
公司的服务器都有一个唯一的不会和其他服务器重复的名字,现在一共有 n 台服务器,这些服务器之间有 m 条数据线连接起来。
如果服务器 x 和 y 之间有一条数据线连接,那么在服务器 x 启动的 t 毫秒后,服务器 y 会自动启动(注意启动是有方向的)。当然如果同时服务器 x 和其他服务器也有数据线连接,而那个服务器在关闭状态,则它也会在相应的时间后自动启动。
现在 TuTu 很好奇,如果他启动了一个服务器 a 那么服务器 b 在多长时间以后会被启动。当然了,好奇的人总是会有很多好奇的点,所以 TuTu 会询问好多个这样的问题。需要注意的是,每一次询问都是独立的。
输入描述:
第一行包含整数 n 和 m (2 <= n <= 1000,1 <= m <= 1000),分别为服务器数量和数据线数量。
接下来的 m 行中,每行包含两个不同的字符串 x[i] 和 y[i] 以及整数 t[i] (1 <= t[i] <= 10^9) ,它们描述一个数据线的连接情况。字符串最多包含 20 个小写字母,表示服务器的名称。保证所有服务器的名称都会至少出现一次。某些服务器对之间可能存在多个数据线连接。
接下来的一行包含整数 q (1 <= q <= 1000),表示询问个数。
接下来的 q 行,每行包含两个不同的字符串 a[i] 和 b[i] ,表示 TuTu 询问启动服务器 a[i] 服务器 b[i] 在多长时间以后会被启动。
输出描述:
输出包含 q 行。每一行独立输出每一次询问所需要花费的时间(以毫秒为单位),如果被询问的服务器 b[i] 永远不能被启动,则输出 INF 。
样例1
输入
3 2
novak goat 1
goat simulator 3
2
novak simulator
simulator goat
输出
4
INF
说明
对于第一个询问,TuTu 启动服务器 novak
,1
毫秒后,服务器 goat
启动,再经过 3
毫秒后所询问的服务器 simulator
启动。
备注:
对于其中
40%
的数据,保证1 <= n <= 10
;
对于其中另外30%
的数据,保证1 <= n <= 100
。
思路
- 降维打击可以看做是单源最短路径问题
- 使用多次迪杰斯特拉算法求解
package main
import "fmt"
const MAXN = 1000 + 10
const INF int64 = 0x3f3f3f3f3f3f3f3f
var fwq map[string]int // 标号
var MAP [MAXN][MAXN]int64 // 邻接矩阵
var n, m int // 结点数(服务器)和单向边数(连接)
// 迪杰斯特拉算法
func Dijkstra(s /*起始结点编号*/ int) {
vis := [MAXN]bool{} // 标记是否访问过
vis[s] = true // 标记访问
// 遍历访问每个中间结点
for i := 0; i < n; i++ {
u := -1 // 记录当前未被访问过的最小路径结点
MIN := INF // 记录当前未被访问结点的最小路径
for j := 0; j < n; j++ { // 遍历寻找未被访问过的最小路径结点
if !vis[j] && MIN > MAP[s][j] {
u = j // 更新结点
MIN = MAP[s][j] // 更新最小路径
}
}
if u == -1 { // 已经遍历完了
return
}
vis[u] = true // 标记已访问
// 更新相连结点的最小路径
for j := 0; j < n; j++ {
if !vis[j] && MAP[u][j] != INF && MAP[s][j] > MAP[s][u]+MAP[u][j] {
MAP[s][j] = MAP[s][u] + MAP[u][j]
}
}
}
}
func main() {
fwq = make(map[string]int)
// 初始化临界矩阵
for i := 0; i < MAXN; i++ {
for j := 0; j < MAXN; j++ {
if i != j {
MAP[i][j] = INF
}
}
}
index := 0 // 标号数目
fmt.Scan(&n, &m)
for i := 0; i < m; i++ {
var a, b string
var time int64
var x, y int
fmt.Scan(&a, &b, &time)
// 记录标号
if _, ok := fwq[a]; ok {
x = fwq[a]
} else {
x = index
fwq[a] = index
index++
}
if _, ok := fwq[b]; ok {
y = fwq[b]
} else {
y = index
fwq[b] = index
index++
}
if MAP[x][y] > time { // 某些服务器对之间可能存在多个连接线
MAP[x][y] = time
}
}
// 多次迪杰斯特拉
for i := 0; i < index; i++ {
Dijkstra(i)
}
/*
此时的邻接矩阵已被修改为最短路径状态数组
如:MAP[i][j]代表结点i到j的最短路径
*/
var q int
fmt.Scan(&q)
// 交互输出
for i := 0; i < q; i++ {
var a, b string
fmt.Scan(&a, &b)
x, y := fwq[a], fwq[b]
if MAP[x][y] == INF {
fmt.Println("INF")
} else {
fmt.Println(MAP[x][y])
}
}
}