提升图最大流算法——关于反向弧的作用的问题,如果它们已经存在于原始输入图中

问题描述

考虑应用最大流算法的以下原始输入图:

enter image description here

The following code(感谢 user sehe)编译并运行良好并提供正确的输出。代码在下面复制以完成:

#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/boykov_kolmogorov_max_flow.hpp>
#include <boost/range/adaptors.hpp>
#include <fmt/ostream.h>
#include <fmt/ranges.h>
using boost::adaptors::filtered;

using Traits = boost::adjacency_list_traits<boost::vecS,boost::vecS,boost::directedS>;
using V      = Traits::vertex_descriptor;
using E      = Traits::edge_descriptor;

using Capacity = double;
using Color    = boost::default_color_type;

struct VertexProps {
    // std::string name;
    Color    color;
    Capacity distance;
    E        preedcessor;
};

struct EdgeProps {
    int      id;
    Capacity weight,residual;
    E        reverse;
};

using Graph = boost::adjacency_list<
    boost::vecS,boost::directedS,VertexProps,// see https://stackoverflow.com/a/64744086/85371 :(
    boost::property<boost::edge_capacity_t,Capacity,EdgeProps>>;

struct MyGraph {
    MyGraph(size_t nnodes) : _g(nnodes) {}

    void runSimulation(std::vector<std::pair<V,V>> const& arcs,std::vector<Capacity> const&        capacities)
    {
        reconfigure(arcs,capacities);

        Capacity maxflow = solve_max_flow(0,3);

        auto cap       = get(boost::edge_capacity,_g);
        auto is_source = [this](V v) { return _g[v].color == Color::black_color; };

        fmt::print("Max flow {}\nNodes {} are in source subset\n",maxflow,vertices(_g) | filtered(is_source));

        for (E e : boost::make_iterator_range(edges(_g))) {
            bool st_cut =
                is_source(source(e,_g)) and
                not is_source(target(e,_g));

            fmt::print("Edge {} (id #{:2}),capacity {:3} {}\n",e,_g[e].id,cap[e],st_cut ? "(ST Cut)" : "");
        }
    }

  private:
    Graph _g;

    void reconfigure(auto const& arcs,auto const& capacities)
    {
        assert(arcs.size() == capacities.size());

        for (auto v : boost::make_iterator_range(vertices(_g))) {
            // boost::clear_out_edges(v,g);
            boost::clear_vertex(v,_g);
        }

        auto cap  = get(boost::edge_capacity,_g);
        auto eidx = get(&EdgeProps::id,_g);
        auto rev  = get(&EdgeProps::reverse,_g);

        auto  eindex = 0;

        for (auto [fr,to] : arcs) {
            auto edf  = add_edge(fr,to,_g).first;
            auto edr  = add_edge(to,fr,_g).first;
            eidx[edf] = 2 * eindex;
            eidx[edr] = eidx[edf] + 1;
            cap[edf]  = cap[edr] = capacities[eindex];

            rev[edf] = edr;
            rev[edr] = edf;

            ++eindex;
        }
    }

    Capacity solve_max_flow(V src,V sink)
    {
        return boykov_kolmogorov_max_flow(
            _g,src,sink,// named arguments
            boost::reverse_edge_map(get(&EdgeProps::reverse,_g))
                .residual_capacity_map(get(&EdgeProps::residual,_g))
                .vertex_color_map(get(&VertexProps::color,_g))
                .predecessor_map(get(&VertexProps::preedcessor,_g))
                .distance_map(get(&VertexProps::distance,_g))
            // end named arguments
        );
    }
};

int main() {
    MyGraph g{4};

    g.runSimulation({{0,1},{0,2},{1,{2,3},3}},{10,1,10,10});

}

我的问题特别涉及弧线 (1->2) 和 (2->1)。

(a) Boost documentation 用于最大流算法要求用户为原始输入图中的每个弧明确提供反向弧。因此,在上面的示例中,有向弧 (1 -> 2) 和 (2 -> 1) 在以下代码段中两次添加到图形对象中:

  auto edf  = add_edge(fr,_g).first; //Arc (1->2) added,Arc (2->1) added
  auto edr  = add_edge(to,_g).first; //Arc (2->1) added,Arc (1->2) added
  eidx[edf] = 2 * eindex;
  eidx[edr] = eidx[edf] + 1;
  cap[edf]  = cap[edr] = capacities[eindex];
  rev[edf] = edr;
  rev[edr] = edf;

虽然在此特定示例中可以看到解决方案的正确性,但是否在所有情况下都能保证?也就是说,将同一弧多次(一次作为正向弧,一次作为反向弧)重复添加到图形对象中是否会导致任何内部内容在针对此问题的 boost 算法中中断?

(b) boost documentation 声明如下:

备注:虽然 push-relabel 方法指出 E^T 中的每条边都有 容量为 0,该算法的反向边为 允许承载能力。如果已经有反向边缘 输入图 G,可以使用那些。这可以将边缘数量减半 并将显着提高性能。

这是否意味着在这种特殊情况下,当我添加正向弧 (1->2) 时,我需要 NOT 明确添加反向弧 (2->1),同样当我添加添加正向弧 (2->1),我需要 NOT 显式添加反向弧 (1->2),如上面代码片段中发生的那样?

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...