code: def longest_path_weighted_nodes(G, source, target, weights=None):
      
      assert nx.is_directed_acyclic_graph(G)
  
      tree = nx.topological_sort(G)
      node_to_index = dict((t, i) for i, t in enumerate(tree))
  
      nnodes = len(tree)
      weights = [weights.get(x, 1) for x in tree] if weights else [1] * nnodes
      score, fromc = weights[:], [-1] * nnodes
      si = node_to_index[source]
      ti = node_to_index[target]
      for a in tree[si: ti]:
          ai = node_to_index[a]
          for b, w in G[a].items():
              bi = node_to_index[b]
              w = w.get('weight', 1)
              d = score[ai] + weights[bi] * w  # Favor heavier edges
              if d <= score[bi]:
                  continue
              score[bi] = d  # Update longest distance so far
              fromc[bi] = ai
  
      # Backtracking
      path = []
      while ti != -1:
          path.append(ti)
          ti = fromc[ti]
  
      path = [tree[x] for x in path[::-1]]
      return path, score[ti]
docs: The longest path problem is the problem of finding a simple path of maximum
      length in a given graph. While for general graph, this problem is NP-hard,
      but if G is a directed acyclic graph (DAG), longest paths in G can be found
      in linear time with dynamic programming.
  
      >>> G = nx.DiGraph([(1, 2), (1, 3), (2, "M"), (3, "M")])
      >>> longest_path_weighted_nodes(G, 1, "M", weights={1: 1, 2: 1, 3: 2, "M": 1})
      ([1, 3, 'M'], 4)