最大流

网络流中最常见的问题就是网络最大流。假定从源点流出的流量足够多,求能够流入汇点的最大流量。解决这个问题最常用的是Ford-Fulkerson算法及其优化。

洛谷模板:https://www.luogu.com.cn/problem/P3376

DFS

用dfs实现的FF算法时间复杂度上界是 O(ef)O(ef) ,其中 e 为边数,f为最大流。

int n, m, s, t; // s是源点,t是汇点
bool vis[MAXN];
int dfs(int p = s, int flow = INF)
{
    if (p == t)
        return flow; // 到达终点,返回这条增广路的流量
    vis[p] = true;
    for (int eg = head[p]; eg; eg = edges[eg].next)
    {
        int to = edges[eg].to, vol = edges[eg].w, c;
        // 返回的条件是残余容量大于0、未访问过该点且接下来可以达到终点(递归地实现)
        // 传递下去的流量是边的容量与当前流量中的较小值
        if (vol > 0 && !vis[to] && (c = dfs(to, min(vol, flow))) != -1)
        {
            edges[eg].w -= c;
            edges[eg ^ 1].w += c;
            // 这是链式前向星取反向边的一种简易的方法
            // 建图时要把cnt置为1,且要保证反向边紧接着正向边建立
            return c;
        }
    }
    return -1; // 无法到达终点
}
inline int FF()
{
    int ans = 0, c;
    while ((c = dfs()) != -1)
    {
        memset(vis, 0, sizeof(vis));
        ans += c;
    }
    return ans;
}

Edmond-Karp算法

其实,EK算法就是BFS实现的FF算法。

它的复杂度上限是 O(ve2)O(ve^2) ,其中 v 为点数。

Dinic算法

然而,最常用的网络流算法是Dinic算法。作为FF/EK算法的优化,它选择了先用BFS分层,再用DFS寻找。它的时间复杂度上界是 O(ev2)O(ev^2)

最后更新于

这有帮助吗?