Graphs

Matrix

matrix = [[0, 0, 0, 0],
		  [0, 0, 0, 0],
		  [0, 0, 0, 0],
		  [0, 0, 0, 0]]

Adjacency Matrix

adjMatrix = [[0, 0, 0, 0],
		  [1, 0, 0, 0],
		  [0, 0, 0, 0],
		  [0, 0, 0, 0]]

Adjacency List

class GraphNode:
	def __init__(self, val):
		self.val = val
		self.neighbors = []
adjList = {"A": [], "B": []}

Topological Sorting

visited = set()  # Regular visit hashset
path = set()  # To check if a node is in the current DFS path (used for cycle detection)
topological_order = []  # Stack to store the topological order

def topologicalSortDFS(node):
    # Cycle detected
    if node in path:
        return True
    
    if node in visited:
        return False
    
    visited.add(node)
    path.add(node)  # Add the node to the current path
    
    for neighbor in adjacencyList[node]:
        if topologicalSortDFS(neighbor):  # If cycle is detected in recursive call
            return True
    
    path.remove(node)  # Remove the node from the current path after processing
    topological_order.append(node)  # Add the node to topological order in postorder
    
    return False  # No cycle found for this path

topological_order.reverse() # needed

Union Find

class UnionFind:
    def __init__(self, n):
        self.nodesParent = list(range(n))
        self.ranking = [0] * n

    def find(self, node):
        """
        Uses path compression to make future queries faster.
        Time: O(α(N)), where α(N) is the inverse Ackermann function.
        """
        if self.nodesParent[node] != node:
            self.nodesParent[node] = self.find(self.nodesParent[node])
        return self.nodesParent[node]

    def union(self, node1, node2):
        """
        Uses union by rank to merge sets efficiently.
        Time: O(α(N)), where α(N) is the inverse Ackermann function.
        """
        parentOfNode1, parentOfNode2 = self.find(node1), self.find(node2)

        if parentOfNode1 == parentOfNode2:
            return False

        if self.ranking[parentOfNode1] > self.ranking[parentOfNode2]:
            self.nodesParent[parentOfNode2] = parentOfNode1
        elif self.ranking[parentOfNode1] < self.ranking[parentOfNode2]:
            self.nodesParent[parentOfNode1] = parentOfNode2
        else:
            self.nodesParent[parentOfNode1] = parentOfNode2
            self.ranking[parentOfNode2] += 1

        return True

Dijkstra's

def networkDelayTime(self, times: List[List[int]], n: int, k: int) -> int:
  edges = collections.defaultdict(list)
  for src, dest, weight in times:
    edges[src].append((dest, weight))

  minHeap = [(0, k)]
  visit = set()
  t = 0
  while minHeap:
    w1, n1 = heapq.heappop(minHeap)
    if n1 in visit:
      continue
    visit.add(n1)
    t = w1

    for n2, w2 in edges[n1]:
      if n2 not in visit:
        heapq.heappush(minHeap, (w1 + w2, n2))
  return t if len(visit) == n else -1

Prim's (Minimum Spanning Tree)

def minCostConnectPoints(self, points: List[List[int]]) -> int:
        adj = defaultdict(list)

        for i in range(len(points)):
            for j in range(len(points)):
                if i == j:
                    continue
                
                iPoint = points[i]
                jPoint = points[j]
                distance = abs(iPoint[0] - jPoint[0]) + abs(iPoint[1] - jPoint[1])

                adj[(iPoint[0], iPoint[1])].append((distance, jPoint[0], jPoint[1]))
                adj[(jPoint[0], jPoint[1])].append((distance, iPoint[0], iPoint[1]))
        
        minimumCost = 0
        minheap = [(0, points[0][0], points[0][1])]
        visited = set()

        while minheap:
            distance, x, y = heapq.heappop(minheap)

            if (x, y) in visited:
                continue
            
            visited.add((x, y))
            # here you can add the current node to the tree
            # and thats your minimum spanning tree
            minimumCost += distance 

            for neighborDistance, neighborX, neighborY in adj[(x, y)]:
                if (neighborX, neighborY) not in visited:
                    heapq.heappush(minheap, (neighborDistance, neighborX, neighborY))

        return minimumCost

Kruskal's

def minimumSpanningTree(edges, n):
	minHeap = []
	for n1, n2, weight in edges:
		heapq.heappush(minHeap, [weight, n1, n2])
	mst = []
	while len(mst) < n - 1:
		_, n1, n2 = heapq.heappop(minHeap)
		if not union(n1, n2):
			continue
		mst.append((n1, n2))
	return mst

Bellman Ford

def findCheapestPrice(self, n: int, flights: List[List[int]], src: int, dst: int, k: int) -> int:
	cost = [float("inf")] * n
	cost[src] = 0

	for _ in range(k + 1):
		temp = cost.copy()

		for frm, to, price in flights:
			if cost[frm] == float("inf"):
				continue
			if cost[frm] + price < temp[to]:
				temp[to] = cost[frm] + price
		cost = temp
	
	return -1 if cost[dst] == float("inf") else cost[dst]