docs: def dfs_conditional(G, source, state, can_cross):
      """
      Example:
          >>> # ENABLE_DOCTEST
          >>> from utool.util_graph import *
          >>> G = nx.Graph()
          >>> G.add_edges_from([(1, 2), (2, 3), (3, 4), (4, 5)])
          >>> G.adj[2][3]['lava'] = True
          >>> G.adj[3][4]['lava'] = True
          >>> def can_cross(G, edge, state):
          >>>     # can only cross lava once, then your lava protection wears off
          >>>     data = G.get_edge_data(*edge)
          >>>     lava = int(data.get('lava', False))
          >>>     if not lava or state == 0:
          >>>         return True, state + lava
          >>>     return False, lava
          >>> assert 5 not in dfs_conditional(G, 1, state=0, can_cross=can_cross)
          >>> G.adj[3][4]['lava'] = False
          >>> assert 5 in dfs_conditional(G, 1, state=0, can_cross=can_cross)
      """
      # stack based version
      visited = {source}
      stack = [(source, iter(G[source]), state)]
      while stack:
          parent, children, state = stack[-1]
          try:
              child = next(children)
              if child not in visited:
                  edge = (parent, child)
                  flag, new_state = can_cross(G, edge, state)
                  if flag:
                      yield child
                      visited.add(child)
                      stack.append((child, iter(G[child]), new_state))
          except StopIteration:
              stack.pop()