平面图欧拉公式
$V - E + 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)