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

请求推荐删除容量为1的边后高效重算maxflow的实现方案

Efficient Max Flow Recomputation After Deleting a Capacity-1 Edge

Great question! When dealing with deleting a capacity-1 edge from a flow network and recomputing max flow efficiently, you don’t need to start from scratch—you can leverage the original max flow’s residual network to avoid redundant work. This approach runs in linear time O(V+E), which is way faster than re-running a full max flow algorithm on large graphs.

Key Insight

Since the edge has capacity 1, there are only two cases to consider:

  1. The edge carries 0 flow in the original max flow: Deleting it has no impact on the max flow—you can just reuse the original result.
  2. The edge carries 1 flow (its full capacity): You need to check if you can reroute this 1 unit of flow through an alternative path. If yes, the max flow stays the same; if no, the max flow decreases by 1.

Python Implementation with igraph

Here’s a step-by-step implementation using igraph’s built-in max flow tools:

Step 1: Compute Original Max Flow

First, calculate the initial max flow and get the residual network:

import igraph as ig

# Assume your graph is already built, with 's' as source and 't' as sink
g = ig.Graph(directed=True)
# ... add nodes and edges with 'capacity' attribute ...

s = 0  # Example source node index
t = len(g.vs) - 1  # Example sink node index

# Compute original max flow
mf = g.maxflow(s, t)
original_flow = mf.flow_value

Step 2: Handle Edge Deletion

Target the edge you want to delete, check its flow, and compute the new max flow:

# Identify the edge to delete (replace with your edge index or source/target)
edge_index = 5  # Example edge index
e = g.es[edge_index]
u = e.source
v = e.target
edge_flow = mf.flow[edge_index]

if edge_flow == 0:
    # Edge wasn't used in the max flow—deletion has no effect
    new_max_flow = original_flow
else:
    # Get the residual network from the original max flow
    residual_g = mf.residual_graph()
    
    # Disable the original edge in the residual network (since we're deleting it)
    try:
        res_edge_id = residual_g.get_eid(u, v)
        residual_g.es[res_edge_id]['capacity'] = 0
    except ig.InternalError:
        # Edge doesn't exist in residual network (already at 0 capacity)
        pass
    
    # BFS to find an alternative augmenting path (capacity ≥1)
    def bfs_find_path(graph, start, end):
        visited = {node: False for node in graph.vs.indices}
        parent = {node: None for node in graph.vs.indices}
        queue = [start]
        visited[start] = True
        
        while queue:
            current = queue.pop(0)
            if current == end:
                break
            # Iterate over outgoing edges with remaining capacity
            for neighbor in graph.neighbors(current, mode='out'):
                edge = graph.es[graph.get_eid(current, neighbor, directed=True)]
                if not visited[neighbor] and edge['capacity'] > 0:
                    visited[neighbor] = True
                    parent[neighbor] = current
                    queue.append(neighbor)
        
        # Reconstruct path if found
        path = []
        current = end
        while parent[current] is not None:
            path.append((parent[current], current))
            current = parent[current]
        return path if path else None
    
    alternative_path = bfs_find_path(residual_g, s, t)
    new_max_flow = original_flow if alternative_path else original_flow - 1

print(f"Original max flow: {original_flow}, New max flow: {new_max_flow}")

C Language Implementation

For even better performance, you can implement this logic in C using an adjacency list for the residual network. Here’s a condensed outline:

Step 1: Represent the Residual Network

Use a struct to represent edges in the residual network:

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <limits.h>

typedef struct Edge {
    int to, rev;  // Target node, index of reverse edge in adjacency list
    int cap;      // Remaining capacity
} Edge;

typedef struct Graph {
    int num_nodes;
    Edge **adj;
    int *adj_size;  // Track size of each adjacency list
} Graph;

// Helper to create a new graph
Graph* create_graph(int n) {
    Graph *g = malloc(sizeof(Graph));
    g->num_nodes = n;
    g->adj = malloc(n * sizeof(Edge*));
    g->adj_size = calloc(n, sizeof(int));
    for (int i=0; i<n; i++) {
        g->adj[i] = malloc(10 * sizeof(Edge));  // Initial buffer size
    }
    return g;
}

// Helper to add an edge to the graph
void add_edge(Graph *g, int from, int to, int cap) {
    // Add forward edge
    Edge forward = {to, g->adj_size[to], cap};
    g->adj[from][g->adj_size[from]++] = forward;
    // Add reverse edge
    Edge reverse = {from, g->adj_size[from]-1, 0};
    g->adj[to][g->adj_size[to]++] = reverse;
}

Step 2: Compute Original Max Flow (Edmonds-Karp)

Implement Edmonds-Karp to get the initial max flow and residual network:

// BFS for Edmonds-Karp
bool bfs(Graph *g, int s, int t, int *parent, int *edge_idx) {
    bool *visited = calloc(g->num_nodes, sizeof(bool));
    int *queue = malloc(g->num_nodes * sizeof(int));
    int front = 0, rear = 0;
    
    queue[rear++] = s;
    visited[s] = true;
    parent[s] = -1;
    
    while (front < rear) {
        int u = queue[front++];
        for (int i=0; i<g->adj_size[u]; i++) {
            Edge *e = &g->adj[u][i];
            if (!visited[e->to] && e->cap > 0) {
                visited[e->to] = true;
                parent[e->to] = u;
                edge_idx[e->to] = i;
                queue[rear++] = e->to;
                if (e->to == t) {
                    free(visited);
                    free(queue);
                    return true;
                }
            }
        }
    }
    free(visited);
    free(queue);
    return false;
}

// Edmonds-Karp algorithm
int edmonds_karp(Graph *g, int s, int t) {
    int flow = 0;
    int *parent = malloc(g->num_nodes * sizeof(int));
    int *edge_idx = malloc(g->num_nodes * sizeof(int));
    
    while (bfs(g, s, t, parent, edge_idx)) {
        int min_cap = INT_MAX;
        // Find minimum capacity along the path
        for (int v = t; v != s; v = parent[v]) {
            int u = parent[v];
            Edge *e = &g->adj[u][edge_idx[v]];
            if (e->cap < min_cap) min_cap = e->cap;
        }
        // Augment the flow
        for (int v = t; v != s; v = parent[v]) {
            int u = parent[v];
            Edge *e = &g->adj[u][edge_idx[v]];
            e->cap -= min_cap;
            g->adj[v][e->rev].cap += min_cap;
        }
        flow += min_cap;
    }
    free(parent);
    free(edge_idx);
    return flow;
}

Step 3: Handle Edge Deletion

After computing the original max flow, locate the edge to delete, set its capacity to 0, and run BFS to check for an alternative path:

int recompute_max_flow_after_deletion(Graph *g, int s, int t, int original_flow, int u, int v) {
    // Find and disable the forward edge u->v
    for (int i=0; i<g->adj_size[u]; i++) {
        Edge *e = &g->adj[u][i];
        if (e->to == v) {
            e->cap = 0;
            break;
        }
    }
    
    // Check for alternative augmenting path
    int *parent = malloc(g->num_nodes * sizeof(int));
    int *edge_idx = malloc(g->num_nodes * sizeof(int));
    bool has_alternative = bfs(g, s, t, parent, edge_idx);
    
    free(parent);
    free(edge_idx);
    return has_alternative ? original_flow : original_flow - 1;
}

This approach avoids the overhead of re-computing max flow from scratch, making it ideal for large graphs where efficiency matters.

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 06:53:12