最大流算法

作者: null12 | 来源:发表于2018-03-23 16:37 被阅读0次

一、网络流模型

1.1 网络流定义

一个流量网络是一张边的权重(这里称为容量)为正的加权有向图。该网络中通常有一个起点s和一个终点t,从起点s出发到达终点t的每一条边都有一个流量上限值(容量),网络流问题就是找到各种流量配置方案,使得每一条边的实际流量小于容量且每个顶点(除s、t)的净流量为0。

术语:
流入量:流向一个顶点的总流量(所有指向该顶点的边中的流量之和)
流出量:流出一个顶点的总流量(由该顶点指出的所有边中的流量之和)
净流量:流入量 - 流出量
最大s-t流量:给定一个s-t流量网络,找到一种流量配置方案,使得s->t的流量最大化

如下是用加权有向图表示网络流问题的模型:

1.2 API定义

流量边的API:

1-2-1 流量网络中边的API

流量边-源码:

public class FlowEdge {
    private final int v; // from
    private final int w; // to
    private final double capacity; // 容量
    private double flow; // 实际流量: v -> w
 
    public FlowEdge(int v, int w, double capacity) {
        if (capacity < 0.0)
            throw new IllegalArgumentException("Edge capacity must be non-negative");
        this.v = v;
        this.w = w;
        this.capacity = capacity;
        this.flow = 0.0;
    }
 
    public int from() {
        return v;
    }
 
    public int to() {
        return w;
    }
 
    public double capacity() {
        return capacity;
    }
 
    public double flow() {
        return flow;
    }
 
    public int other(int vertex) {
        if (vertex == v)
            return w;
        else if (vertex == w)
            return v;
        else
            throw new IllegalArgumentException("invalid endpoint");
    }
 
    /**
     * 返回边的流量
     * 
     * @return 如果顶点vertex是该边的起始顶点,返回边的实际流量
     *         如果顶点vertex是该边的结束顶点,返回边的剩余流量
     */
    public double residualCapacityTo(int vertex) {
        if (vertex == v)
            return flow; // backward edge
        else if (vertex == w)
            return capacity - flow; // forward edge
        else
            throw new IllegalArgumentException("invalid endpoint");
    }
 
    /**
     * 增加/减少边的流量
     * 如果顶点vertex是该边的起始顶点,则减少边的流量
     * 如果顶点vertex是该边的结束顶点,则增加边的流量
     */
    public void addResidualFlowTo(int vertex, double delta) {
        if (delta < 0.0)
            throw new IllegalArgumentException("Delta must be nonnegative");
 
        if (vertex == v)
            flow -= delta; // backward edge
        else if (vertex == w)
            flow += delta; // forward edge
        else
            throw new IllegalArgumentException("invalid endpoint");
 
        if (flow < 0.0)
            throw new IllegalArgumentException("Flow is negative");
        if (flow > capacity)
            throw new IllegalArgumentException("Flow exceeds capacity");
    }
 
    public String toString() {
        return v + "->" + w + " " + flow + "/" + capacity;
    }
}

流量网络的API:

1-2-2 流量网络API 1-2-3 流量网络示意图

流量网络的源码:

public class FlowNetwork {
    private final int V; // 顶点数
    private int E; // 边数
    private Bag<FlowEdge>[] adj; // adj[v]表示顶点v的所有出边
 
    public FlowNetwork(int V) {
        if (V < 0)
            throw new IllegalArgumentException("Number of vertices in a Graph must be nonnegative");
        this.V = V;
        this.E = 0;
        adj = (Bag<FlowEdge>[]) new Bag[V];
        for (int v = 0; v < V; v++)
            adj[v] = new Bag<FlowEdge>();
    }
    public FlowNetwork(In in) {
        int V = in.readInt();
        this(V);
        int E = in.readInt();
        if (E < 0)
            throw new IllegalArgumentException("number of edges must be nonnegative");
        for (int i = 0; i < E; i++) {
            int v = in.readInt(); // 起始顶点
            int w = in.readInt(); // 结束顶点
            double capacity = in.readDouble(); // 容量
            addEdge(new FlowEdge(v, w, capacity));
        }
    }
 
    public int V() {
        return V;
    }
    public int E() {
        return E;
    }
    public void addEdge(FlowEdge e) {
        int v = e.from();
        int w = e.to();
        adj[v].add(e);
        adj[w].add(e);
        E++;
    }
    public Iterable<FlowEdge> adj(int v) {
        return adj[v];
    }
 
    // return list of all edges - excludes self loops
    public Iterable<FlowEdge> edges() {
        Bag<FlowEdge> list = new Bag<FlowEdge>();
        for (int v = 0; v < V; v++)
            for (FlowEdge e : adj(v)) {    //只保存顶点v的出边
                if (e.to() != v)
                    list.add(e);
            }
        return list;
    }
 
    public String toString() {
        StringBuilder s = new StringBuilder();
        s.append(V + " " + E + "\n");
        for (int v = 0; v < V; v++) {
            s.append(v + ":  ");
            for (FlowEdge e : adj[v]) {
                if (e.to() != v)
                    s.append(e + "  ");
            }
            s.append("\n");
        }
        return s.toString();
    }
}

二、最大流算法

2.1 Ford-Fulkerson算法

2.1.1 定义

Ford - Fulkerson 最大流量算法,网络中的初始流量为零,沿着任意从起点到终点(且不含有饱和的正向边或空逆向边)的增广路增大流量,直到网络中不存在这样的路径为止。

相关文章

  • 网络流——Ford-Fulkerson 算法

    最大流算法 Ford-Fulkerson 算法是用于计算容量网络 < V,E,c,s,t> 的最大流的算法。该算法...

  • 【模板】网络最大流Edmonds-Karp算法

    关于网络最大流的资料Edmonds_Karp 算法 (转)USACO 4.2.1 Ditch 网络最大流问题算法小结

  • 最大流模板(Maximum Flow)

    最大流模板(Maximum Flow) 一篇写得通俗易懂介绍最大流的文章:最大流模板【EdmondsKarp算法,...

  • 分布式存储系统的分容灾块数据分布算法

    本算法是基于最小费用最大流算法建模,读者需要对最小费用最大流算法有一定的基础,要能理解这个例题 http://ww...

  • 最大流算法

    一、网络流模型 1.1 网络流定义 一个流量网络是一张边的权重(这里称为容量)为正的加权有向图。该网络中通常有一个...

  • 【算法】最大流

    概述 在最大流问题中,我们希望在不违反任何容量限制的情况下,计算出从源节点运送物料到汇点的最大速率 流网络 流网络...

  • 最小费用最大流

    转载自这里最小费用最大流通过EK,Dinic,ISAP算法可以得到网络流图中的最大流,一个网络流图中最大流的流量m...

  • 分布式架构

    大流量限流/削峰 常见的限流算法 计数器算法池化资源技术的限流就是通过计数器算法来控制全局的总并发数。 令牌桶算法...

  • 二分图匹配和匈牙利算法

    内容概要: 最大流算法解决二分图最大匹配 匈牙利算法 LeetCode上一个困难问题:覆盖 匹配问题相关概念 该类...

  • 2020-5-9《大流感·最致命瘟疫的史诗》

    【主题】1918年的大流感 【书籍】《大流感——最致命瘟疫的史诗》 【作者】【美】约翰·M·巴里(John M. ...

网友评论

    本文标题:最大流算法

    本文链接:https://www.haomeiwen.com/subject/npyxcftx.html