算法 - 图论07(Swift版本)

28 阅读2分钟

求最小生成树

题目1:寻宝

Kruskal 求最小生成树讲解

Prim 求最小生成树讲解

prim求最小生成树:
维护minDis数组 记录所有节点距离最小生成树的 最小距离。
依次遍历加入最小生成树, 然后更新minDis记录表。

Kruskal求最小生成树:
将边按权值从小到大排序, 然后依次加入最小生成树。
如果已经在同一个集合就不加入, 如果不在一个集合则加入。 使用并查集判断是否在同一集合。

// v 顶点数  e 边数   path[i] [a, b, val] -> ab节点相连,权重为val
// 无向有权图
// prim 算法
func minPath(v: Int, e: Int, grid: [[Int]]) -> Int {
    // 最大距离为10000
    var map = Array(repeating: Array(repeating: 10001, count: v + 1), count: v + 1)
    // 每个节点距离最小生成树的 最小距离记录表
    var minDisList = Array(repeating: 10001, count: v + 1)
    // 节点是否在最小生成树里
    var inTree = Array(repeating: 0, count: v + 1)
    var paths = Array(repeating: 0, count: v + 1)
    for path in grid {
        // 无向图
        map[path[0]][path[1]] = path[2]
        map[path[1]][path[0]] = path[2]
    }
    for _ in 1...v {
        // 先找距离 最小生成树 距离最近的节点,准备加入最小生成树
        var cur = 0
        var minDistance = Int.max 
        for (j, dis) in minDisList.enumerated() {
            if dis < minDistance, inTree[j] == 0 {
                minDistance = dis 
                cur = j
            }
        }
        // 加入到最小生成树
        inTree[cur] = 1
        // 更新 记录表
        for (j, dis) in minDisList.enumerated() {
            // 当前节点不在生成树中, 并且和最近加入的树中的cur节点 做更新。
            if inTree[j] == 0 && map[cur][j] < dis { 
                minDisList[j] = map[cur][j]
                paths[j] = cur
             }
        }
    }
    paths.enumerated().forEach { print("\($0) - \($1)") }
    var res = 0
    for i in 2...v {
        res += minDisList[i]
    }
    return res 
}
let dis = minPath(v: 7, e: 11, grid: [[1, 2, 1], [1, 3, 1], [1, 5, 2], [2, 6, 1], [2, 4, 2], [2, 3, 2], [3, 4, 1], [4, 5, 1], [5, 6, 2], [5, 7, 1], [6, 7, 1]])
print("\(dis)")


// cruskal 算法
func minPath(v: Int, e: Int, grid: [[Int]]) -> Int {
    // 将边按权值从小到大排序, 然后依次加入最小生成树。 如果已经在同一个集合就不加入, 如果不在一个集合则加入。 使用并查集判断是否在同一集合。 
    let grid = grid.sorted { $0[2] < $1[2] }
    // 并查集
    var parent = Array(repeating: 0, count: v + 1)
    for i in 1...v {
        parent[i] = i
    }
    func root(_ u: Int) -> Int {
        if u == parent[u] { return u }
        parent[u] = root(parent[u])
        return parent[u]
    }
    func isSame(_ u: Int, _ v: Int) -> Bool {
        root(u) == root(v)
    }
    func join(_ u: Int, _ v: Int) {
        let u = root(u)
        let v = root(v)
        if u == v { return }
        parent[v] = u
    }
    var res = 0
    var paths = [[Int]]()
    for edge in grid {
        if isSame(edge[0], edge[1]) { continue }
        join(edge[0], edge[1])
        paths.append(edge)
        res += edge[2]
    }
    paths.forEach { print("\($0[0]) - \($0[1])")}
    return res
}
let dis = minPath(v: 7, e: 11, grid: [[1, 2, 1], [1, 3, 1], [1, 5, 2], [2, 6, 1], [2, 4, 2], [2, 3, 2], [3, 4, 1], [4, 5, 1], [5, 6, 2], [5, 7, 1], [6, 7, 1]])
print("\(dis)")