# CSPT27 Lecture 14
## All Paths from Source to Target
```
from collections import deque, defaultdict
class Solution:
"""
1. Translate the problem into graph terminology
vertices - each index in the list aka graph[i]
edges - graph[i][j] aka each sublist is that node's neighbors
2. build your graph
We don't need to build out a graph, we can just traverse the graph
that's given to us
3. Traverse the graph
We need to do a search for the path to the last node
Type of search doesn't matter (DFS/BFS)
"""
def allPathsSourceTarget(self, graph: List[List[int]]) -> List[List[int]]:
res = []
self.allPathsSourceTargetHelper(graph, 0, len(graph) - 1, [0], res)
return res
def allPathsSourceTargetHelper(self, graph, currNode, destinationNode, currPath, res):
if currNode == destinationNode:
res.append(currPath)
else:
for neighbor in graph[currNode]:
newPath = currPath.copy()
newPath.append(neighbor)
self.allPathsSourceTargetHelper(graph, neighbor, destinationNode, newPath, res)
def bfsAllPathsSourceTarget(self, graph: List[List[int]]) -> List[List[int]]:
destinationNode = len(graph) - 1
queue = deque()
queue.append((0, [0]))
res = []
while len(queue) > 0:
curr = queue.popleft()
currNode, currPath = curr[0], curr[1]
if currNode == destinationNode:
res.append(currPath)
else:
for neighbor in graph[currNode]:
newPath = currPath.copy()
newPath.append(neighbor)
queue.append((neighbor, newPath))
return res
def dfsAllPathsSourceTarget(self, graph: List[List[int]]) -> List[List[int]]:
destinationNode = len(graph) - 1
stack = deque()
stack.append((0, [0]))
res = []
while len(stack) > 0:
curr = stack.pop()
currNode, currPath = curr[0], curr[1]
if currNode == destinationNode:
res.append(currPath)
else:
for neighbor in graph[currNode]:
newPath = currPath.copy()
newPath.append(neighbor)
stack.append((neighbor, newPath))
return res
```
## Flood-fill
```
from collections import deque
class Solution:
"""
Plan
1. Translate the problem into graph terminology
Not exactly a graph, but we can treat a matrix very similar to a graph where a node
will be an element in the matrix. And its neighbors will be the ones right next to it.
2. Build your graph
Just traverse the matrix/image that's given to you
3. Traverse the graph
Use a stack/queue to push neighboring pixels and keep traversing the image
Change the pixels value if its the value you want to change
Ignore pixels which have a different value
"""
def floodFill(self, image: List[List[int]], sr: int, sc: int, newColor: int) -> List[List[int]]:
colorToChange = image[sr][sc]
queue = deque()
queue.append((sr, sc))
visited = set()
numRows, numCols = len(image), len(image[0])
while len(queue) > 0:
currPoint = queue.popleft()
currRow, currColumn = currPoint[0], currPoint[1]
if currPoint in visited:
continue
if currRow < 0 or currRow >= numRows or currColumn < 0 or currColumn >= numCols:
continue
if image[currRow][currColumn] != colorToChange:
continue
visited.add(currPoint)
image[currRow][currColumn] = newColor
queue.append((currRow + 1, currColumn))
queue.append((currRow - 1, currColumn))
queue.append((currRow, currColumn - 1))
queue.append((currRow, currColumn + 1))
return image
```
## Find Eventual Safe States
```
from collections import defaultdict
class Solution:
UNVISITED = 0
VISITING = 1
SAFE = 3
UNSAFE = 4
def eventualSafeNodes(self, graph: List[List[int]]) -> List[int]:
numNodes = len(graph)
state = [Solution.UNVISITED] * numNodes
for node in range(numNodes):
if state[node] == Solution.UNVISITED:
self.dfs(graph, node, state)
return [node for (node, nodeState) in enumerate(state) if nodeState == Solution.SAFE]
def dfs(self, graph, currNode, state):
if state[currNode] == Solution.SAFE:
return True
if state[currNode] == Solution.VISITING or state[currNode] == Solution.UNSAFE:
return False
state[currNode] = Solution.VISITING
isSafe = True
for neighbor in graph[currNode]:
isSafe &= self.dfs(graph, neighbor, state)
if not isSafe:
break
state[currNode] = Solution.SAFE if isSafe else Solution.UNSAFE
return isSafe
```