算法 - 图论08(Swift版本)

5 阅读1分钟

拓扑排序 和 最短路径

题目1:拓扑排序

讲解

每次找入度为0的点,然后移除它。 依次进行就是 节点的顺序就是 遵循依赖的。

func tuopuSort(n: Int, m: Int, grid: [[Int]]) {
    // 入度统计
    var digree = Array(repeating: 0, count: n) 
    // 结果
    var res = [Int]()
    // 邻接表统计依赖关系
    var map = Array(repeating: [Int](), count: n)

    for i in grid {
        let s = i[0]
        let t = i[1]
        map[s].append(t)
        digree[t] += 1
    }
    print("\(digree)")
    print("\(map)")
    var queue = [Int]()
    for (i, d) in digree.enumerated() {
        if d == 0 {
            queue.append(i)
        }
    }
    while !queue.isEmpty {
        let node = queue.removeFirst()
        res.append(node)
        for i in map[node] {
            digree[i] -= 1
            if digree[i] == 0 {
                queue.append(i)
            }
        }
    }
    if res.count == n {
        res.forEach { print("\($0)") }
    } else {
        print("-1")
    }
}
tuopuSort(n: 5, m: 4, grid: [[0, 1], [0, 2], [1, 3], [2, 4]])

题目2:最短路径

dijkstra算法, 类似于prim算法。
这里求的有向有权图。

维护minDis列表,每次选择最近的点加入已访问列表, 然后更新minDis列表。 依次进行。
最后minDis里面的值 即是每个元素距离起点最短的路径。

讲解



func minPathInDirectionMap(n: Int, e: Int, grid: [[Int]]) {
    var visited = Array(repeating: 0, count: n + 1)
    // 记录每个点 距离源点的最小距离
    var minDis = Array(repeating: Int.max, count: n + 1) 
    var map = Array(repeating: Array(repeating: Int.max, count: n + 1), count: n + 1)
    for i in grid {
        map[i[0]][i[1]] = i[2]
    }
    // 源点距离为0
    minDis[1] = 0
    var path = Array(repeating: -1, count: n + 1)
    // 遍历N轮
    for _ in 1...n {
        // 1. 取最近节点
        // 2. 标记为已访问
        // 3. 更新minDis数组
        var cur = 1
        var minVal = Int.max
        for i in 1...n {
            if visited[i] == 0, minDis[i] < minVal {
                minVal = minDis[i]
                cur = i
            }
        }
        visited[cur] = 1
        for i in 1...n {
            if visited[i] == 0, map[cur][i] != Int.max, minDis[cur] + map[cur][i] < minDis[i] {
                minDis[i] = minDis[cur] + map[cur][i]
                // 这里 会有未被用到的路径 被记录进来。
                path[i] = cur
            }
        }
    }
    if minDis[n] == Int.max {
        print("无法到达终点")
    } else {
        print("\(minDis[n])")
        path.enumerated().forEach { print("\($1) -> \($0)")}
    }
}
minPathInDirectionMap(n: 7, e: 9, grid:[[1, 2, 1], [1, 3, 4], [2, 3, 2], [2, 4, 5], [3, 4, 2], [4, 5, 3], [2, 6, 4], [5, 7, 4], [6, 7, 9]])