You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

求有向无环图(DAG)的K条最长路径的Python/伪代码实现

Hey there, I get it—hunting for working code to find the top-K longest paths in a DAG can be frustrating even after digging through papers. Let's walk through a practical implementation based on the approach from that research you referenced, with both pseudocode and runnable Python code you can test right away.

Top-K Longest Paths in a DAG: Practical Implementation

Core Idea

Since DAGs have no cycles, we can use topological sorting to process nodes in an order where all predecessors are handled before the node itself. For each node, we'll track the top-K longest paths ending at that node. When processing a node's neighbors, we merge the current node's paths with the neighbor's existing paths, then trim down to keep only the top-K entries. This avoids redundant calculations and ensures we only keep the most relevant paths.

Pseudocode Outline

This breaks down the logic step-by-step for clarity:

1. Perform topological sort on the DAG to get a processing order [n₁, n₂, ..., nₘ]
2. Initialize for every node u:
   - paths[u]: List of the top-K paths ending at u (starts with just [u] with length 0 if u is a source node)
   - lengths[u]: List of path lengths corresponding to paths[u]
3. For each node u in topological order:
   - For each neighbor v of u (connected by an edge u→v with weight w):
     - Generate candidate paths: Take each path in paths[u], append v, and calculate new length (original length + w)
     - Merge these candidates with v's existing paths and lengths
     - Sort the merged entries by length in descending order, remove duplicate paths, then keep only the top-K
     - Update paths[v] and lengths[v] with this trimmed list
4. After processing all nodes, collect all paths from every node's path list, sort them by length descending, and pick the top-K unique paths

Runnable Python Code

This implementation assumes your DAG is represented as an adjacency list, where each entry graph[u] contains tuples (v, weight) for edges from u to v.

from collections import deque

def top_k_longest_paths_dag(graph, k):
    # Step 1: Compute in-degrees and perform topological sort
    in_degree = {node: 0 for node in graph}
    for u in graph:
        for v, _ in graph[u]:
            in_degree[v] += 1
    
    # Initialize queue with source nodes (nodes with in-degree 0)
    queue = deque([node for node in in_degree if in_degree[node] == 0])
    topo_order = []
    
    while queue:
        u = queue.popleft()
        topo_order.append(u)
        for v, _ in graph[u]:
            in_degree[v] -= 1
            if in_degree[v] == 0:
                queue.append(v)
    
    # Step 2: Initialize paths and lengths for each node
    node_paths = {node: [] for node in graph}
    node_lengths = {node: [] for node in graph}
    
    # Source nodes start with their own trivial path (length 0)
    for node in [n for n in in_degree if in_degree[n] == 0]:
        node_paths[node] = [[node]]
        node_lengths[node] = [0]
    
    # Step 3: Process nodes in topological order
    for u in topo_order:
        current_paths = node_paths[u]
        current_lengths = node_lengths[u]
        
        for v, weight in graph[u]:
            # Generate candidate paths extending from u to v
            candidate_paths = [path + [v] for path in current_paths]
            candidate_lengths = [length + weight for length in current_lengths]
            
            # Merge with v's existing paths
            merged_paths = node_paths[v] + candidate_paths
            merged_lengths = node_lengths[v] + candidate_lengths
            
            # Sort by length descending, then remove duplicate paths
            sorted_pairs = sorted(zip(merged_lengths, merged_paths), key=lambda x: (-x[0], x[1]))
            unique_pairs = []
            seen_paths = set()
            
            for length, path in sorted_pairs:
                path_tuple = tuple(path)
                if path_tuple not in seen_paths:
                    seen_paths.add(path_tuple)
                    unique_pairs.append((length, path))
            
            # Keep only the top-K paths for v
            top_k_pairs = unique_pairs[:k]
            node_lengths[v] = [pair[0] for pair in top_k_pairs]
            node_paths[v] = [pair[1] for pair in top_k_pairs]
    
    # Step 4: Collect all paths and extract the final top-K
    all_paths = []
    all_lengths = []
    for node in graph:
        all_paths.extend(node_paths[node])
        all_lengths.extend(node_lengths[node])
    
    # Sort all paths by length descending, remove duplicates
    sorted_all = sorted(zip(all_lengths, all_paths), key=lambda x: (-x[0], x[1]))
    final_seen = set()
    top_k_result = []
    
    for length, path in sorted_all:
        path_tuple = tuple(path)
        if path_tuple not in final_seen:
            final_seen.add(path_tuple)
            top_k_result.append((length, path))
            if len(top_k_result) == k:
                break
    
    return top_k_result

# Example Usage
if __name__ == "__main__":
    # Sample DAG with weighted edges
    sample_dag = {
        'A': [('B', 3), ('C', 2)],
        'B': [('D', 4), ('C', 1)],
        'C': [('D', 2)],
        'D': []
    }
    k_value = 3
    longest_paths = top_k_longest_paths_dag(sample_dag, k_value)
    
    print(f"Top {k_value} longest paths in the sample DAG:")
    for i, (length, path) in enumerate(longest_paths, 1):
        print(f"{i}. Path: {' -> '.join(path)} | Length: {length}")

Notes for Optimization

  • For large-scale DAGs, instead of fully sorting merged paths, you can use a min-heap to maintain only the top-K entries. This reduces time complexity from O(m log m) to O(m log k) per merge step.
  • If your DAG has unweighted edges, just set all edge weights to 1 and the code will still work.
  • The code handles duplicate paths (same nodes in order) to avoid redundant entries in the final result.

内容的提问来源于stack exchange,提问作者Sina Faezi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.26 09:58:12