858. Prim算法求最小生成树

摘要
Title: 858. Prim算法求最小生成树
Tag: Prim、最小生成树
Memory Limit: 64 MB
Time Limit: 1000 ms

Powered by:NEFU AB-IN

Link

858. Prim算法求最小生成树

  • 题意

    给定一个 n 个点 m 条边的无向图,图中可能存在重边和自环,边权可能为负数。
    求最小生成树的树边权重之和,如果最小生成树不存在则输出 impossible。
    给定一张边带权的无向图 G=(V,E),其中 V 表示图中点的集合,E 表示图中边的集合,n=|V|,m=|E|。
    由 V 中的全部 n 个顶点和 E 中 n−1 条边构成的无向连通子图被称为 G 的一棵生成树,其中边的权值之和最小的生成树被称为无向图 G 的最小生成树。

  • 思路

    最小生成树和二分图汇总
    img

    注意

    • 稠密图一般用 朴素版的Prim
    • 稀疏图一般用 Kruskal

    朴素版的Prim
    Prim

    与朴素版的Dijkstra区别
    区别1

    • Dijkstra的t,是不在最短路集合中的离起点最近的点
    • Prim的t,是集合外最近的点

    区别2

    • Dijkstra是用t来更新其他点到起点的距离
    • Prim是用t来更新其他点到集合的距离

    区别3

    • Dijkstra外层迭代n - 1次
    • Prim外层迭代n次

    注意:

    • 集合是指当前已经在连通块中的点
    • u到集合的距离:u到集合内的点的最短距离
  • 代码

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    '''
    Author: NEFU AB-IN
    Date: 2022-03-03 18:52:55
    FilePath: \ACM\Acwing\858.py
    LastEditTime: 2022-03-03 19:13:17
    '''
    N = 550
    INF = int(2e9)
    g = [[INF] * N for _ in range(N)]
    st, dist = [0] * N, [INF] * N


    def prim():
    res = 0
    for i in range(n): #迭代n次
    t = -1
    for j in range(1, n + 1): #选出最小的
    if (st[j] == 0 and (t == -1 or dist[t] > dist[j])):
    t = j
    if i and dist[t] == INF: #如果不是第一个点,并且最小的距离为INF,那么不存在
    return INF
    if i:
    res += dist[t] #如果不是第一个点,那么加上距离
    for j in range(1, n + 1):
    dist[j] = min(dist[j], g[j][t]) #用t更新距离,是对集合的,所以不加dist[t]
    st[t] = 1
    return res


    n, m = map(int, input().split())
    for i in range(m):
    x, y, z = map(int, input().split())
    g[x][y] = g[y][x] = min(g[x][y], z) #双向边
    res = prim()
    if res == INF:
    print("impossible")
    else:
    print(res)
使用搜索:谷歌必应百度