有向圖判斷有環
拓撲排序
if __name__ == "__main__":
v = [[0, 0, 0, 0, 1], [1, 0, 0, 0, 0], [0, 0, 0, 1, 1], [0, 0, 0, 0, 0], [0, 1, 0, 0, 0]]
e = [[]]
in_v = {}
cnt = 0
visited = set()
circle = []
# 計算每個點的入度
for i in range(len(v)):
for j in range(len(v)):
if v[i][j] == 1:
if j not in in_v.keys():
in_v[j] = 0
in_v[j] += 1
# 拓撲
# 入度爲0的點,加入到visited中
change = True
while change:
change = False
for node in range(len(v)):
if node not in visited and (node not in in_v.keys() or in_v[node] == 0):
change = True
visited.add(node)
for j in range(len(v)):
if v[node][j] == 1:
in_v[j] -= 1
# 沒有被visited的,即爲環
for node in range(len(v)):
if node not in visited:
circle.append(node)
print(circle)
應用:
給定一堆序列標號(標號用整數),形式爲[a,b],表示標號爲a,b的兩個物體的體積關係滿足:a > b,用合適的數據結構存儲數據,並判斷這堆序列是否有效。(比如[a,b], [b, d], [d, a]這個就不是有效的,因爲a > b, b > d, 那麼 a > d, 但是最後一個序列說的是 d > a,矛盾了。)
思路:
題目實際是,求圖中是否有環,用拓撲結構,把入度爲0的結點全部刪掉,直到刪不動爲止。
# 有向圖判斷有環:拓撲算法
def hasCircel(inputs):
graph = {}
in_v = {}
nodes = set()
# 用字典存每個點連接的點
# 保存每個點入度
for pair in inputs:
a,b = pair
nodes.add(a)
nodes.add(b)
if a not in graph.keys():
graph[a] = [b]
else:
graph[a].append(b)
if b not in in_v.keys():
in_v[b] = 0
in_v[b] += 1
# 拓撲判斷是否有環:
# 入度爲0的點刪去,它相關的出度點入度-1,不斷迭代
nodes = list(nodes)
visted = [False]*len(nodes)
change = True
while change:
change = False
for i in range(len(nodes)):
if not visted[i] and (nodes[i] not in in_v.keys() or in_v[nodes[i]] == 0):
visted[i] = True
change = True
if nodes[i] in graph.keys():
connect_nodes = graph[nodes[i]]
for node in connect_nodes:
in_v[node] -= 1
for i in range(len(nodes)):
if not visted[i]:
return False
return True
if __name__ == '__main__':
inputs = [[1, 2], [2, 3], [3, 1]]
res = hasCircel(inputs)
print(res)
Dijkstra算法(單源最短路徑)
貪心思想實現的,首先把起點到所有點的距離存下來找個最短的,然後鬆弛一次再找出最短的,所謂的鬆弛操作就是,遍歷一遍看通過剛剛找到的距離最短的點作爲中轉站會不會更近,如果更近了就更新距離,這樣把所有的點找遍之後就存下了起點到其他所有點的最短距離。
具體實現參考:
https://blog.csdn.net/lbperfect123/article/details/84281300
Floyd(多源最短路徑)
https://blog.csdn.net/shezjoe/article/details/80670188