算法87-----DAG有向無環圖的拓撲排序
一、題目:課程排表---210
課程表上有一些課,是必須有修學分的先後順序的,必須要求在上完某些課的情況下才能上下一門。問是否有方案修完所有的課程?如果有的話請返回其中一個符合要求的路徑,否則返回[].
例子1:
Input: 2, [[1,0]]
Output: [0,1]
Explanation: There are a total of 2 courses to take. To take course 1 you should have finished
course 0. So the correct course order is [0,1].
例子2:
Input: 4, [[1,0],[2,0],[3,1],[3,2]]
Explanation: There are a total of 4 courses to take. To take course 3 you should have finished both
courses 1 and 2. Both courses 1 and 2 should be taken after you finished course 0.
So one correct course order is [0,1,2,3]. Another correct ordering is [0,2,1,3] .
BFS思路:每次找入度為0的節點。
1、先建立圖(鄰接表)、和入度表。
2、循環n次(n為節點數),每次找到度為0 的節點(循環n次,從頭開始找),加入path中,然後將其出度的節點的入度-=1(循環入度表)。
先是找到入度為0的節點:1 將1加入path中,然後是2,3節點的入度減去1,因為1已經被處理掉了。 此時度為0的節點是2,3。 將2,3加入path中,…… |
|
偽代碼:
循環n次:
循環n次:
找入度為0的節點
將度為0節點加入path中
循環入度表:
將度為0節點的出度節點的入度節點-=1
代碼:
from collections import defaultdict def BFS(n,arr): # n 為節點數,arr為【【u1,v1】,【u2,v2】……】,這裏的u和v中,v是u的父節點。 if not arr: return -1 graph = defaultdict(list) indegree = defaultdict(int) path = [] for u , v in arr: graph[v].append(u) indegree[u] += 1 for i in range(n): zeroDegree = False for j in range(n): if indegree[j] == 0: zeroDegree = True break if not zeroDegree: return [] indegree[j] -= 1 path.append(j) for val in graph[j]: indegree[val] -= 1 return path n= 5 arr = [[1,0],[2,0],[3,1],[3,2],[4,0]] print(BFS(n,arr))
DFS思路:遞歸
1、建立圖
2、循環n次,每次是遍歷一個節點是否已經visited且合法地加入path中了,如果False不合法則直接返回【】。
3、遍歷一個節點時會將其後面的所有子節點都處理掉。
如,先是1,將1進行dfs處理【path中加入1,2,4,8,5】 然後是2,將2進行dfs處理,已經visited過了,繼續循環 然後是3,將3進行dfs處理,沒有visited,unkown狀態,【path=【1,2,4,8,5】中加入【3,6,7】】 然後是4……,後面都是visited過的,都直接跳過。 |
代碼:
from collections import defaultdict def findPath(n,arr): if n == 0: return [] graph = defaultdict(list) for u , v in arr: graph[v].append(u) # 0為Unkown,1為visiting,2為visited path = [] visited = [0] * n for i in range(n): if not DFS(graph,visited,path,i): return [] return path def DFS(graph,visited,path,i): ####i節點:其正在遍歷,但它的子節點的子節點也是它,表示產生了有環,則return FALSE if visited[i] == 1: return False ####i節點 :已經遍歷過,後面已經沒有節點了,return true elif visited[i] == 2:return True ####表示正在遍歷i節點 visited[i] = 1 for j in graph[i]: if not DFS(graph,visited,path,j): return False path.append(i) visited[i] = 2 return True n = 5 arr = [[1,0],[2,0],[3,1],[3,2],[4,0]] print(findPath(n,arr))
二、題目:解題報告,連除----399
已經給出了某些變量的比值,求新的變量的比值。如果這個變量沒有出現過,或者不可到達,那麽返回-1.
DFS思路:
題目中給了頂點和頂點之間的關系,其實就是制定了這個圖的樣子。然後要求的新的比值其實就是從一個頂點到達另外一個頂點的路徑,並且把這條路徑上所有的權重相乘。
註意,如果a/b=3,那麽從a到b是3,那麽從b到a是1/3.
既然是從一個頂點出發到達另外一個頂點,所以應該是dfs解決的問題。
原文:https://blog.csdn.net/fuxuemingzhu/article/details/82591165
1、建立圖 {a:{b : 2.0} 、b:{a:1 /2.0,c:3.0}、c:{b:1/3.0}}
2、不在圖中則返回-1
3、在圖中,x == y,返回1,x != y,返回x到y的拓撲排序的權重相乘值。
代碼:
from collections import defaultdict def solveque(arr ,values , que): if not arr: return [-1] * len(que) if not que: return [] graph = defaultdict(dict) for (x,y) , value in zip(arr,values): graph[x][y] = value graph[y][x] = 1/value if value else 0 for x,y in que: if x in graph and y in graph: return dfs(graph,x,y,set()) else: return -1.0 def dfs(graph,x,y,visited): if x == y: return 1.0 visited.add(x) for k in graph[x]: if k in visited:continue visited.add(k) d = dfs(graph,k,y,visited) if d > 0: return d*graph[x][k] return -1.0 arr = [[‘a‘,‘b‘],[‘b‘,‘c‘]] values = [2.0,3.0] que = [[‘a‘,‘c‘],[‘a‘,‘v‘]] print(solveque(arr ,values , que))
算法87-----DAG有向無環圖的拓撲排序