depth first search , topological sort
class Solution(object):
def canFinish(self, numCourses, prerequisites):
"""
:type numCourses: int
:type prerequisites: List[List[int]]
:rtype: bool
"""
#graph[y] is a list of nodes with an edge from y, y's children nodes
graph=[[]for _ in range(numCourses)]
#visit 0:unvisited -1:being visited 1:visited
visit=[0]*numCourses
for x,y in prerequisites:
graph[y].append(x)
#print graph
def dfs(i):
#print 'visiting node',i
if visit[i]==-1:return False
if visit[i]==1:return True
elif visit[i]==0:
visit[i]=-1
for node in graph[i]:
if not dfs(node):
return False
visit[i]=1
return True
for i in range(numCourses):
if not dfs(i):
return False
return True
breadth first search, Kahn's algorithm
class Solution(object):
def canFinish(self, numCourses, prerequisites):
"""
:type numCourses: int
:type prerequisites: List[List[int]]
:rtype: bool
"""
#graph_in store the incoming edges of all nodes, the prerequisites for each course
#graph_out store the outgoing edges of all nodes, courses that needs the particular prerequisite
graph_in,graph_out=collections.defaultdict(set),collections.defaultdict(set)
for x,y in prerequisites:
graph_in[x].add(y)
graph_out[y].add(x)
#store nodes without any incoming edges
s=set([i for i in range(numCourses) if i not in graph_in])
while s:
n=s.pop()
#traverse all the children node of n
for node in graph_out[n]:
graph_in[node].discard(n)
if not graph_in[node]:#if the last incoming edge has been deleted, then delete the node from graph_in
del graph_in[node]
s.add(node)
#if there is still edges left in the graph, then its cyclic
if graph_in:
return False
return True