练习题-POJ-1502:MPI漩涡
描述
BIT 最近接收了他们的新超级计算机,这是一台 32 处理器的 Apollo Odyssey 分布式共享内存机器,带有一个分层通信子系统。Valentine McKee 的研究顾问 Jack Swigert 已要求她对新系统进行基准测试。
“由于 Apollo 是分布式共享内存机器,内存访问和通信时间并不统一,”Valentine 告诉 Swigert。``共享同一内存子系统的处理器之间的通信速度很快,但不在同一子系统上的处理器之间的通信速度较慢。Apollo 和我们实验室的机器之间的通信速度还比较慢。‘’
“Apollo 的消息传递接口 (MPI) 端口如何工作?” Swigert 问道。
“不太好,”瓦伦丁回答。``要从一个处理器向所有其他 n-1 个处理器广播消息,它们只需执行 n-1 次发送序列。这真的使事情连载并扼杀了表演。‘’
“你能做些什么来解决这个问题吗?”
“是的,”瓦伦丁笑着说。``有。一旦第一个处理器将消息发送给另一个处理器,这两个处理器就可以同时向另外两个主机发送消息。然后会有四个可以发送的主机,以此类推。‘’
``啊,所以你可以将广播作为二叉树!‘’
``不是真正的二叉树——我们应该利用我们网络的一些特殊功能。我们拥有的接口卡允许每个处理器同时向与其连接的任意数量的其他处理器发送消息。然而,消息不一定同时到达目的地——这涉及到通信成本。一般来说,我们需要考虑网络拓扑中每个链路的通信成本,并相应地计划以最小化进行广播所需的总时间。
输入
输入将描述连接 n 个处理器的网络拓扑。输入的第一行将是 n,处理器的数量,使得 1 <= n <= 100。
输入的其余部分定义邻接矩阵 A。邻接矩阵是正方形,大小为 nx n。它的每个条目要么是整数,要么是字符 x。A(i,j) 的值表示从节点 i 直接向节点 j 发送消息的费用。A(i,j) 的 x 值表示消息不能直接从节点 i 发送到节点 j。
请注意,节点向自身发送消息不需要网络通信,因此 A(i,i) = 0 for 1 <= i <= n。此外,您可以假设网络是无向的(消息可以以相同的开销向任一方向传播),因此 A(i,j) = A(j,i)。因此,只会提供 A 的(严格)下三角形部分上的条目。
程序的输入将是 A 的下三角形部分。也就是说,输入的第二行将包含一个条目 A(2,1)。下一行将包含两个条目,A(3,1) 和 A(3,2),依此类推。
输出
您的程序应该输出从第一个处理器向所有其他处理器广播消息所需的最短通信时间。
样本输入
5
50
30 5
100 20 50
10×10
样本输出
35
思路
- 这道题实质上就是要求单源最短路径,由于需要广播到所有其他处理器所以要出输出到各结点最短路径的最大值
package main
import (
"fmt"
"strconv"
)
const INF = 0x3f3f3f3f
func dijkstra(graph [][]int, start int) []int {
n := len(graph)
visit := make([]bool, n)
dist := make([]int, n)
for i := 0; i < n; i++ {
dist[i] = graph[start][i]
}
visit[start] = true
var mn, md int
for i := 0; i < n; i++ {
mn = 0
md = INF
for j := 0; j < n; j++ {
if !visit[j] && md > dist[j] {
md = dist[j]
mn = j
}
}
for j := 0; j < n; j++ {
if !visit[j] && dist[j] > dist[mn]+graph[mn][j] {
dist[j] = dist[mn] + graph[mn][j]
}
}
visit[mn] = true
}
return dist
}
func main() {
var n, d int
fmt.Scan(&n)
gp := make([][]int, n)
for i := 0; i < n; i++ {
gp[i] = make([]int, n)
}
var m string
for i := 0; i < n-1; i++ {
for j := 0; j <= i; j++ {
fmt.Scan(&m)
if m == "x" {
gp[i+1][j] = INF
gp[j][i+1] = INF
} else {
d, _ = strconv.Atoi(m)
gp[i+1][j] = d
gp[j][i+1] = d
}
}
}
dist := dijkstra(gp, 0)
var res int
for i := 0; i < n; i++ {
if res < dist[i] {
res = dist[i]
}
}
fmt.Println(res)
}