Loading

代码解释:Edmonds-Karp算法实现网络最大流

当你了解网络流是什么原理时,你才知道到这有多难用文字解释

这段代码实现了网络最大流的Edmonds-Karp算法,下面我将分部分详细解释:

1. 数据结构和变量定义

int n,m,s,t,u,v;
long long w,ans,dis[520010];
int tot=1,vis[520010],pre[520010],head[520010],flag[2510][2510];

struct node {
    int to,net;
    long long val;
} e[520010];
  • n:节点数量
  • m:边数量
  • s:源点
  • t:汇点
  • u,v,w:临时变量,用于输入边的起点、终点和容量
  • ans:存储最终的最大流结果
  • dis:记录从源点到当前节点的路径上的最小剩余容量
  • tot:边的计数器,从1开始(方便反向边计算)
  • vis:标记节点是否被访问过
  • pre:记录增广路径中每个节点的前驱边
  • head:邻接表头指针
  • flag:处理重边(合并相同方向的边)
  • e:边的结构体数组,存储图的邻接表

2. 添加边的函数

inline void add(int u,int v,long long w) {
    e[++tot].to=v;
    e[tot].val=w;
    e[tot].net=head[u];
    head[u]=tot;
    e[++tot].to=u;
    e[tot].val=0;
    e[tot].net=head[v];
    head[v]=tot;
}
  • 每次添加一条正向边(容量为w)和一条反向边(容量为0)
  • 使用邻接表存储图结构
  • 反向边的索引是正向边索引的异或1(这就是为什么tot从1开始)

3. BFS寻找增广路径

inline int bfs() {
    for(register int i=1;i<=n;i++) vis[i]=0;
    queue<int> q;
    q.push(s);
    vis[s]=1;
    dis[s]=2005020600;
    while(!q.empty()) {
        int x=q.front();
        q.pop();
        for(register int i=head[x];i;i=e[i].net) {
            if(e[i].val==0) continue;
            int v=e[i].to;
            if(vis[v]==1) continue;
            dis[v]=min(dis[x],e[i].val);
            pre[v]=i;
            q.push(v);
            vis[v]=1;
            if(v==t) return 1;
        }
    }
    return 0;
}
  • 使用BFS寻找从源点到汇点的增广路径
  • dis数组记录路径上的最小剩余容量
  • pre数组记录路径信息
  • 找到增广路径返回1,否则返回0

4. 更新网络流

inline void update() {
    int x=t;
    while(x!=s) {
        int v=pre[x];
        e[v].val-=dis[t];
        e[v^1].val+=dis[t];
        x=e[v^1].to;
    }
    ans+=dis[t];
}
  • 从汇点回溯到源点
  • 更新路径上所有边的剩余容量
  • 正向边减去流量,反向边增加流量
  • 累加本次增广的流量到总结果中

5. 主函数

int main() {
    scanf("%d%d%d%d",&n,&m,&s,&t);
    for(register int i=1;i<=m;i++) {
        scanf("%d%d%lld",&u,&v,&w);
        if(flag[u][v]==0) {
            add(u,v,w);
            flag[u][v]=tot;
        }
        else {
            e[flag[u][v]-1].val+=w;
        }
    }
    while(bfs()!=0) {
        update();
    }
    printf("%lld",ans);
    return 0;
}
  • 读取输入数据
  • 处理重边(合并相同方向的边)
  • 不断寻找增广路径并更新网络流,直到没有增广路径为止
  • 输出最大流结果

算法特点

  1. Edmonds-Karp算法:这是Ford-Fulkerson方法的一种实现,使用BFS寻找增广路径
  2. 时间复杂度:O(VE²),适合小规模网络
  3. 反向边技巧:通过添加反向边来实现"撤销"操作
  4. 重边处理:合并相同方向的边,提高效率

这个实现虽然使用了Edmonds-Karp算法而不是更高效的Dinic或ISAP算法,但代码结构清晰,适合理解网络流的基本原理。对于题目给定的数据规模(n≤200),这个实现完全足够。

posted @ 2025-07-17 11:23  Venlacy  阅读(55)  评论(0)    收藏  举报