---
# System prepended metadata

title: CSPT27 Lecture 14

---

# 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
```