code: def dom_lt(graph):
      
  
      def _dfs(v, n):
          semi[v] = n = n + 1
          vertex[n] = label[v] = v
          ancestor[v] = 0
          for w in graph.all_sucs(v):
              if not semi[w]:
                  parent[w] = v
                  n = _dfs(w, n)
              pred[w].add(v)
          return n
  
      def _compress(v):
          u = ancestor[v]
          if ancestor[u]:
              _compress(u)
              if semi[label[u]] < semi[label[v]]:
                  label[v] = label[u]
              ancestor[v] = ancestor[u]
  
      def _eval(v):
          if ancestor[v]:
              _compress(v)
              return label[v]
          return v
  
      def _link(v, w):
          ancestor[w] = v
  
      parent, ancestor, vertex = {}, {}, {}
      label, dom = {}, {}
      pred, bucket = defaultdict(set), defaultdict(set)
  
      # Step 1:
      semi = {v: 0 for v in graph.nodes}
      n = _dfs(graph.entry, 0)
      for i in range(n, 1, -1):
          w = vertex[i]
          # Step 2:
          for v in pred[w]:
              u = _eval(v)
              y = semi[w] = min(semi[w], semi[u])
          bucket[vertex[y]].add(w)
          pw = parent[w]
          _link(pw, w)
          # Step 3:
          bpw = bucket[pw]
          while bpw:
              v = bpw.pop()
              u = _eval(v)
              dom[v] = u if semi[u] < semi[v] else pw
      # Step 4:
      for i in range(2, n + 1):
          w = vertex[i]
          dw = dom[w]
          if dw != vertex[semi[w]]:
              dom[w] = dom[dw]
      dom[graph.entry] = None
      return dom
docs: Dominator algorithm from Lengauer-Tarjan