Python算法参考---图论部分

平面图欧拉公式

V − E + F = 2 V - E + F = 2 VE+F=2

其实中V是顶点数,E是边数,F是面数


堆优化版本dijkstra

import heapq
INF = 0x3f3f3f3f
N = 1000000

e = [0] * N
idx = 0
ne = [0] * N
w = [0] * N
h = [-1] * N
n, m = map(int, input().split())

def add(a, b, c):
    global e, w, ne ,h, idx
    e[idx] = b
    w[idx] = c
    ne[idx] = h[a]
    h[a]= idx
    idx += 1

while m:
     m -= 1
     a, b, c = map(int, input().split())
     add(a, b, c)

def dijkstra():
    st = [False] * N
    dist = [INF] * N
    dist[1] = 0
    hp = []
    heapq.heappush(hp, (0, 1))

    while len(hp):
        t = heapq.heappop(hp)
        cur = t[1]; dis = t[0]

        if st[cur]: continue
        st[cur] = True

        i = h[cur]
        while ~i:
            j = e[i]
            if dist[j] > dist[cur] + w[i]: 
                dist[j] = dist[cur] + w[i]
                heapq.heappush(hp, (dist[j], j))
            i = ne[i]
        
    return -1 if dist[n] == INF else dist[n]

print(dijkstra())

Dijkstra

n , m = map(int , input().split())
N = n + 1000
g = [[0x3f3f3f3f]*N for i in range(N)]
while m:
    m -= 1
    x , y , z = map(int , input().split())
    g[x][y] = z
for  i in range(n):
    g[i][i] = 0
def dijkstra():
    st = [False] * N
    dist = [0x3f3f3f3f] * N
    dist[1] = 0
    for i in range(n-1):
        t = -1
        for j in range(1,n+1):
            if not st[j] and (t == -1 or dist[j] < dist[t]): t = j
        for j in range(1,n+1):
            dist[j] = min(dist[j] , dist[t] + g[t][j])
        
        st[t] = True
    return -1 if dist[n] == 0x3f3f3f3f else dist[n]

print(dijkstra())

Bellman_ford

两层循环,复杂度O(nm)

最外层循环意味着当前最短路包含几条边

'''
用来求单源最短路
算法思想:
扫描每一条边(x, y, z),若dist[y] > dist[x] + z,则用dist[x] + z 更新dist[y]
'''
import copy
class edge(): # a, b, w分别表示起点和终点以及权值
    a = 0
    b = 0
    w = 0
    def __init__(self, a, b, w):
        self.a = a
        self.b = b
        self.w = w

n, m, k = map(int, input().split())
g = [None] * m

for i in range(m):
    a, b, w = map(int, input().split())
    g[i] = edge(a, b, w)

def bellman_ford():
    dis = [0x3f3f3f3f3f] * (n + 1)
    dis[1] = 0 
    for i in range(k):
        backup = copy.deepcopy(dis)#backup是dis列表的拷贝,防止下面那层循环在更新dis数组时用到本层循环中刚更新过的dis
        for j in range(m):
            dis[g[j].b] = min(dis[g[j].b], backup[g[j].a] + g[j].w)
    return dis[n]

ans = bellman_ford()

if ans > 0x3f3f3f3f: print('impossible')
else: print(ans)

SPFA

from collections import deque
def spfa():
    dist = [0x3f3f3f3f] * (n + 1)
    v = [0] * (n + 1)
    q = deque()
    q.append(1)
    dist[1] = 0
    while len(q):
        pos = q.popleft()
        v[pos] = 0
        i = head[pos]
        while ~i:
            j = e[i]
            if dist[j] > dist[pos] + w[i]:
                dist[j] = dist[pos] + w[i]
                if not v[j]: q.append(j); v[j] = 1
            i = ne[i]
    return 'impossible' if dist[n] == 0x3f3f3f3f else dist[n]
  

Kruskal

'''
将边排序,每次选取边权最小的边,利用并查集判断该边两端点是否在同一个集合即可
'''
'''
e 用来存储边
n 点数
m 边数
ans 最小生成树代价
cnt 选取得总边数
'''
n, m = map(int, input().split())

class edge():
    a = 0
    b = 0
    w = 0
    def __init__(self, a = 0, b = 0, c = 0):
        self.a = a
        self.b = b
        self.w = c

e = [edge() for i in range(m)]
fa = [i for i in range(n + 1)]
for i in range(m):
    a, b, c = map(int, input().split())
    e[i].a = a
    e[i].b = b
    e[i].w = c

e.sort(key = lambda x: x.w)

def find(x):
    if x == fa[x]:
        return fa[x]
    else:
        fa[x] = find(fa[x])
        return fa[x]
ans = 0
cnt = 0
for i in e:
    x = i.a
    y = i.b
    x = find(x)
    y = find(y)
    if x != y:
        fa[x] = y
        ans += i.w
        cnt += 1
if cnt < n - 1:
    print('impossible')
else:
    print(ans)
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值