提出 #73407755


ソースコード 拡げる

//utf-8

#include <vector>
#include <cstdint>
#include <string>
#include <algorithm>
#include <limits>
#include <iterator>
#include <utility>

#include <cassert>
#include <iostream>

#include <exception>

#define bound_flow_less_edge

namespace flow_algo {

    using size_t = std::uint32_t;
    using flow_t = std::uint64_t;
    using cost_t = std::int64_t;
    using std::vector;
    using std::basic_string;
    using std::forward;
    using signed_flow_t = std::int64_t;
    using std::pair;
    using std::make_pair;
    using std::swap;
    using std::runtime_error;

    constexpr flow_t flow_max_v = std::numeric_limits<flow_t>::max();

    struct edge {
        size_t to;
        flow_t flow;
        edge(size_t t = -1, flow_t fl = 1) : to(t), flow(fl) {}
        bool empty() const { return to == (size_t)-1; }
    };

    struct network {
        vector<edge> edges;
        vector<vector<size_t> > vertexs;
        size_t source, sink;// 源汇
        network() : edges{}, vertexs{}, source{}, sink{} {}
        void set_vertex(size_t n, size_t S, size_t T){
            edges.clear();
            vertexs.clear();
            vertexs.resize(n);
            source = S, sink = T;
        }
        void clear(){
            set_vertex(0, 0, 0);
        }
        typedef size_t edge_handle;
        edge_handle add_edge(size_t from, size_t to, flow_t flow = 1){
            size_t ret = edges.size();
            edges.emplace_back(to, flow);
            edges.emplace_back(from, 0);
            vertexs[from].emplace_back(ret);
            vertexs[to].emplace_back(++ret);
            return (edges.size() - 2) >> 1;
        }
        void reset(edge_handle idx){
            edges[idx << 1].flow += edges[idx << 1 | 1].flow;
            edges[idx << 1 | 1].flow = 0;
        }
        void clear(edge_handle idx){
            edges[idx << 1].flow = edges[idx << 1 | 1].flow = 0;
        }
        void grow_flow(edge_handle idx, flow_t fl){
            edges[idx << 1].flow += fl;
        }
        flow_t flow_of(edge_handle idx) const {
            return edges[idx << 1 | 1].flow;
        }
        flow_t capacity_of(edge_handle idx) const {
            return edges[idx << 1].flow + edges[idx << 1 | 1].flow;
        }
        void reset_flow(){
            for (size_t i = 0, _ = edges.size(); i != _; i += 2)
                edges[i].flow += edges[i ^ 1].flow, edges[i ^ 1].flow = 0;
        }

        flow_t EK_max_flow(){// EK 算法
            size_t n = vertexs.size();
            vector<size_t> pre(n);
            vector<flow_t> dis(n);
            auto bfs = [&]{
                std::fill_n(dis.begin(), n, 0);
                basic_string<bool> vis; vis.resize(n);
                std::fill_n(pre.begin(), n, 0);
                vector<size_t> queue(n);
                vector<size_t>::iterator head = queue.begin(), tail = std::next(head);
                vis[*head = source] = true;
                dis[source] = flow_max_v;
                while (head != tail){
                    size_t u = *head; ++head;
                    for (size_t id : vertexs[u]){
                        size_t to = edges[id].to;
                        flow_t fl = edges[id].flow;
                        if (fl && !vis[to]){
                            dis[to] = std::min(dis[u], fl);
                            vis[to] = true, pre[to] = id, *tail = to, ++tail;
                        }
                    }
                }
                return (bool)dis[sink];
            };
            flow_t ret = 0;
            while (bfs()){
                ret += dis[sink];
                for (size_t u = sink; u != source; u = edges[pre[u] ^ 1].to)
                    edges[pre[u]].flow -= dis[sink], edges[pre[u] ^ 1].flow += dis[sink];
            }
            return ret;
        }

        flow_t DINIC_max_flow(flow_t max_flow = flow_max_v){// Dinic 算法
            if (!max_flow)return 0;
            typedef vector<size_t>::iterator iter_t;
            size_t n = vertexs.size();
            vector<size_t> d(n);
            vector<size_t> now(n);// 当前弧优化
            auto bfs = [&]{
                std::fill_n(d.begin(), n, 0);
                std::fill_n(now.begin(), n, 0);
                vector<size_t> queue(n);
                iter_t head = queue.begin(), tail = std::next(head);
                *head = source;
                d[source] = 1;
                while (head != tail){
                    size_t u = *head; ++head;
                    for (size_t id : vertexs[u]){
                        size_t to = edges[id].to;
                        flow_t fl = edges[id].flow;
                        if (fl && !d[to])d[to] = d[u] + 1, *tail = to, ++tail;
                    }
                }
                return (bool)d[sink];
            };
            auto dfs = [&](size_t u, flow_t sm){
                auto dfs_ = [&](auto &&self, size_t u, flow_t sm) -> flow_t {
                    if (u == sink)return sm;
                    flow_t ret = 0;
                    for (iter_t it = vertexs[u].begin() + now[u], end = vertexs[u].end(); it != end; ++it, ++now[u]){
                        size_t to = edges[*it].to;
                        flow_t &fl = edges[*it].flow;
                        if (fl && d[to] == d[u] + 1){
                            flow_t nx = self(self, to, std::min(sm, fl));
                            if (!nx)d[to] = -1;
                            else {
                                fl -= nx, sm -= nx, ret += nx;
                                edges[*it ^ 1].flow += nx;
                                if (!sm)return ret;
                            }
                        }
                    }
                    return ret;
                };
                return dfs_(dfs_, u, sm);
            };
            flow_t ret = 0;
            while (bfs() && ret < max_flow)ret += dfs(source, max_flow - ret);
            return ret;
        }

        vector<size_t> min_cut() const {// 返回 S 集合中的点,在残量网络上求
            typedef vector<size_t>::iterator iter_t;
            size_t n = vertexs.size();
            basic_string<bool> vs; vs.resize(n);
            vector<size_t> ret;
            vector<size_t> queue(n);
            iter_t head = queue.begin(), tail = std::next(head);
            *head = source;
            vs[source] = true;
            ret.emplace_back(source);
            while (head != tail){
                size_t u = *head; ++head;
                for (size_t id : vertexs[u]){
                    size_t to = edges[id].to;
                    if (edges[id].flow && !vs[to]){
                        vs[to] = true;
                        ret.emplace_back(to);
                        *tail = to;
                        ++tail;
                    }
                }
            }
            return ret;
        }

        bool reach(size_t from, size_t to){
            typedef vector<size_t>::iterator iter_t;
            size_t n = vertexs.size();
            vector<size_t> queue(n);
            basic_string<bool> d;d.resize(n);
            iter_t head = queue.begin(), tail = std::next(head);
            *head = from;
            while (head != tail){
                size_t u = *head; ++head;
                for (size_t id : vertexs[u]){
                    size_t t = edges[id].to;
                    flow_t fl = edges[id].flow;
                    if (fl && !d[t]){
                        if (t == to)return true;
                        d[t] = d[u] + 1, *tail = t, ++tail;
                    }
                }
            }
            return false;
        }

        typedef flow_t flow_result_t;

        flow_t flow(size_t _S, size_t _T, flow_t max_flow = flow_max_v){
            if (!max_flow)return 0;
            swap(source, _S), swap(sink, _T);
            flow_t ret = DINIC_max_flow(max_flow);
            swap(source, _S), swap(sink, _T);
            return ret;
        }

        flow_t remove(edge_handle id){ // 删除边并退流,返回退的流量,保证删除之后网络合法,但不保证删除后的网络无增广路
            size_t from = edges[id << 1 | 1].to, to = edges[id << 1].to;
            flow_t flw = edges[id << 1 | 1].flow;
            flow(sink, to, flw);
            flow(from, source, flw);
            edges[id << 1].flow = edges[id << 1 | 1].flow = 0;
            return flw;
        }

    };

    struct edge_with_cost {
        size_t to;
        flow_t flow;
        cost_t cost;
        edge_with_cost(size_t t = -1, flow_t fl = 1, cost_t cs = 1) : to(t), flow(fl), cost(cs) {}
        bool empty() const { return to == (size_t)-1; }
    };

    struct cost_and_flow {
        cost_t cost;
        flow_t flow;
        cost_and_flow(cost_t cs, flow_t fl) : cost(cs), flow(fl) {}
    };

    struct network_with_cost {
        vector<edge_with_cost> edges;
        vector<vector<size_t> > vertexs;
        size_t source, sink;
        network_with_cost() : edges{}, vertexs{}, source{}, sink{} {}
        void set_vertex(size_t n, size_t S, size_t T){
            edges.clear();
            vertexs.clear();
            vertexs.resize(n);
            source = S, sink = T;
        }
        typedef size_t edge_handle;
        edge_handle add_edge(size_t from, size_t to, flow_t fl, cost_t cs){
            size_t ret = edges.size();
            edges.emplace_back(to, fl, cs);
            edges.emplace_back(from, 0, -cs);
            vertexs[from].emplace_back(ret);
            vertexs[to].emplace_back(++ret);
            return (edges.size() - 2) >> 1;
        }
        void reset(edge_handle idx){
            edges[idx << 1].flow += edges[idx << 1 | 1].flow;
            edges[idx << 1 | 1].flow = 0;
        }
        void clear(edge_handle idx){
            edges[idx << 1].flow = edges[idx << 1 | 1].flow = 0;
        }
        flow_t flow_of(edge_handle idx) const {
            return edges[idx << 1 | 1].flow;
        }
        flow_t capacity_of(edge_handle idx) const {
            return edges[idx << 1].flow + edges[idx << 1 | 1].flow;
        }
        void grow_flow(edge_handle idx, flow_t fl){
            edges[idx << 1].flow += fl;
        }
        void set_cost(edge_handle idx, cost_t cs){
            edges[idx << 1].cost = cs;
            edges[idx << 1 | 1].cost = -cs;
        }
        void reset_flow(){
            for (size_t i = 0, _ = edges.size(); i != _; i += 2)
                edges[i].flow += edges[i ^ 1].flow, edges[i ^ 1].flow = 0;
        }

        cost_and_flow EK_min_cost(bool flow_max = true){
            size_t n = vertexs.size();
            vector<size_t> pre(n);
            vector<flow_t> dis(n);
            vector<cost_t> dcs(n);
            auto spfa = [&]{
                std::fill_n(dis.begin(), n, 0);
                basic_string<bool> inq; inq.resize(n);
                std::fill_n(pre.begin(), n, 0);
                std::fill_n(dcs.begin(), n, std::numeric_limits<cost_t>::max());
                vector<size_t> queue(n);
                vector<size_t>::iterator head = queue.begin(), tail = std::next(head);
                inq[*head = source] = true;
                dcs[source] = 0;
                dis[source] = flow_max_v;
                while (head != tail){
                    size_t u = *head; ++head;
                    inq[u] = false;
                    for (size_t id : vertexs[u]){
                        size_t to = edges[id].to;
                        flow_t fl = edges[id].flow;
                        cost_t cs = edges[id].cost;
                        if (fl && dcs[to] > dcs[u] + cs){
                            dcs[to] = dcs[u] + cs, pre[to] = id;
                            dis[to] = std::min(dis[u], fl);
                            if (!inq[to]){
                                inq[to] = true;
                                if (__builtin_expect(tail == queue.end(), false)){
                                    size_t new_size = queue.size() << 1, count = tail - head;
                                    queue.erase(queue.begin(), head);
                                    if (new_size > uint64_t(n * n * n * 2))
                                        throw runtime_error("network_with_cost::EK_min_cost : Containing negative rings.");
                                    queue.resize(new_size);
                                    head = queue.begin();
                                    tail = head + count;
                                }
                                *tail = to, ++tail;
                            }
                        }
                    }
                }
                return dcs[sink] != std::numeric_limits<cost_t>::max();
            };
            flow_t max_flow = 0;
            cost_t min_cost = 0;
            while (spfa()){
                if (!flow_max && dcs[sink] > 0)break;
                max_flow += dis[sink];
                min_cost += dis[sink] * dcs[sink];
                for (size_t u = sink; u != source; u = edges[pre[u] ^ 1].to)
                    edges[pre[u]].flow -= dis[sink], edges[pre[u] ^ 1].flow += dis[sink];
            }
            return cost_and_flow(min_cost, max_flow);
        }

        cost_and_flow EK_max_cost(bool flow_max = true){
            size_t n = vertexs.size();
            vector<size_t> pre(n);
            vector<flow_t> dis(n);
            vector<cost_t> dcs(n);
            auto spfa = [&]{
                std::fill_n(dis.begin(), n, 0);
                basic_string<bool> inq; inq.resize(n);
                std::fill_n(pre.begin(), n, 0);
                std::fill_n(dcs.begin(), n, std::numeric_limits<cost_t>::lowest());
                vector<size_t> queue(n);
                vector<size_t>::iterator head = queue.begin(), tail = std::next(head);
                inq[*head = source] = true;
                dcs[source] = 0;
                dis[source] = flow_max_v;
                while (head != tail){
                    size_t u = *head; ++head;
                    inq[u] = false;
                    for (size_t id : vertexs[u]){
                        size_t to = edges[id].to;
                        flow_t fl = edges[id].flow;
                        cost_t cs = edges[id].cost;
                        if (fl && dcs[to] < dcs[u] + cs){
                            dcs[to] = dcs[u] + cs, pre[to] = id;
                            dis[to] = std::min(dis[u], fl);
                            if (!inq[to]){
                                inq[to] = true;
                                if (__builtin_expect(tail == queue.end(), false)){
                                    size_t new_size = queue.size() << 1, count = tail - head;
                                    queue.erase(queue.begin(), head);
                                    if (new_size > uint64_t(n * n * n * 2))
                                        throw runtime_error("network_with_cost::EK_max_cost : Containing positive rings.");
                                    queue.resize(new_size);
                                    head = queue.begin();
                                    tail = head + count;
                                }
                                *tail = to, ++tail;
                            }
                        }
                    }
                }
                return dcs[sink] != std::numeric_limits<cost_t>::lowest();
            };
            flow_t max_flow = 0;
            cost_t max_cost = 0;
            while (spfa()){
                if (!flow_max && dcs[sink] < 0)break;
                max_flow += dis[sink];
                max_cost += dis[sink] * dcs[sink];
                for (size_t u = sink; u != source; u = edges[pre[u] ^ 1].to)
                    edges[pre[u]].flow -= dis[sink], edges[pre[u] ^ 1].flow += dis[sink];
            }
            return cost_and_flow(max_cost, max_flow);
        }

        enum type {
            min_cost,
            max_cost
        };

        typedef cost_and_flow flow_result_t;

        cost_and_flow flow(type t, bool flow_max = true){
            return t == min_cost? EK_min_cost(flow_max) : EK_max_cost(flow_max);
        }

    };

    struct edge_without_weight {// 二分图中,0<=u<left 为左部点,0<=v<right 为右部点
        size_t u, v;
        edge_without_weight() : u(-1), v(-1) {}
        edge_without_weight(size_t x, size_t y) : u(x), v(y) {}
    };

    struct bipartite_graph_info {
        size_t left, right;
        size_t source, sink;
        network net;
        size_t middle_edge;//[0,middle_edge) -> middle
    };

    template <typename iter_t,
            typename = std::enable_if_t<std::is_same<typename std::iterator_traits<iter_t>::value_type, edge_without_weight>::value> >
        bipartite_graph_info bipartite_graph(size_t left, size_t right, iter_t edge_bg, iter_t edge_ed){
            bipartite_graph_info ret;
            ret.left = left, ret.right = right;
            ret.source = left + right, ret.sink = ret.source + 1;
            ret.net.set_vertex(left + right + 2, ret.source, ret.sink);
            for (; edge_bg != edge_ed; ++edge_bg)
                ret.net.add_edge(edge_bg->u, edge_bg->v + left);
            ret.middle_edge = ret.net.edges.size();
            for (size_t i = 0; i < left; ++i)ret.net.add_edge(ret.source, i);
            for (size_t i = 0; i < right; ++i)ret.net.add_edge(left + i, ret.sink);
            return ret;
        }

    // 二分图最大匹配 网络流
    vector<edge_without_weight> max_match_flow(bipartite_graph_info &bigr){// 返回匹配边
        vector<edge_without_weight> ret;
        ret.reserve(bigr.net.DINIC_max_flow());
        for (size_t i = 0; i != bigr.middle_edge; i += 2)
            if (bigr.net.edges[i ^ 1].flow)ret.emplace_back(bigr.net.edges[i ^ 1].to, bigr.net.edges[i].to - bigr.left);
        return ret;
    }

    // 匈牙利算法
    vector<edge_without_weight> max_match_km(bipartite_graph_info &bigr){// 返回匹配边
        vector<size_t> match(bigr.right, -1);
        vector<vector<size_t> > G(bigr.left);
        for (size_t i = 0; i != bigr.middle_edge; i += 2)
            G[bigr.net.edges[i ^ 1].to].emplace_back(bigr.net.edges[i].to - bigr.left);
        vector<size_t> vis(bigr.left, -1);
        auto find = [&](auto &&self, size_t left_point, size_t vis_time) -> bool {
            if (vis[left_point] == vis_time)return false;
            vis[left_point] = vis_time;
            for (size_t right_point : G[left_point])
                if (match[right_point] == (size_t)-1 || self(self, match[right_point], vis_time)){
                    match[right_point] = left_point;
                    return true;
                }
            return false;
        };
        for (size_t i = 0; i < bigr.left; ++i)find(find, i, i);
        vector<edge_without_weight> ret;
        for (size_t i = 0; i < bigr.right; ++i)
            if (~match[i])ret.emplace_back(match[i], i);
        return ret;
    }

    // 二分图最小点覆盖
    vector<size_t> minimum_point_coverage(bipartite_graph_info &bigr){
        //[0,left) and [left,left+right)
        bigr.net.DINIC_max_flow();
        basic_string<bool> inS; inS.resize(bigr.left + bigr.right);
        for (auto t : bigr.net.min_cut())inS[t] = true;
        vector<size_t> ret;
        for (size_t i = 0; i < bigr.left; ++i)if (!inS[i])ret.emplace_back(i);
        for (size_t i = bigr.left, _ = bigr.left + bigr.right; i < _; ++i)if (inS[i])ret.emplace_back(i);
        return ret;
    }

    // 二分图最大独立集
    vector<size_t> maximum_independent_set(bipartite_graph_info &bigr){
        //[0,left) and [left,left+right)
        bigr.net.DINIC_max_flow();
        basic_string<bool> inS; inS.resize(bigr.left + bigr.right);
        for (auto t : bigr.net.min_cut())inS[t] = true;
        vector<size_t> ret;
        for (size_t i = 0; i < bigr.left; ++i)if (inS[i])ret.emplace_back(i);
        for (size_t i = bigr.left, _ = bigr.left + bigr.right; i < _; ++i)if (!inS[i])ret.emplace_back(i);
        return ret;
    }

    template <typename iter_t,
            typename = std::enable_if_t<std::is_same<typename std::iterator_traits<iter_t>::value_type, edge_without_weight>::value> >
        vector<vector<size_t> > DAG_path_cover(size_t n, iter_t edge_bg, iter_t edge_ed){
            network net;
            size_t source = n << 1, sink = source + 1;
            net.set_vertex(sink + 1, source, sink);
            for (; edge_bg != edge_ed; ++edge_bg)
                net.add_edge(edge_bg->u, edge_bg->v + n);
            size_t mid = net.edges.size();
            for (size_t i = 0; i < n; ++i){
                net.add_edge(source, i);
                net.add_edge(i + n, sink);
            }
            vector<vector<size_t> > ret;
            ret.reserve(n - net.DINIC_max_flow());
            vector<vector<size_t> > G(n);
            vector<size_t> indegree(n);
            for (size_t i = 0; i < mid; i += 2)
                if (net.edges[i ^ 1].flow)
                    G[net.edges[i ^ 1].to].emplace_back(net.edges[i].to - n), ++indegree[net.edges[i].to - n];
            for (size_t i = 0; i < n; ++i)
                if (!indegree[i]){
                    ret.emplace_back();
                    size_t u = i;
                    ret.back().emplace_back(u);
                    while (!G[u].empty())
                        ret.back().emplace_back(u = G[u][0]);
                }
            return ret;
        }

    vector<size_t> max_match_must_pass_vertex(bipartite_graph_info &bigr){// 最大匹配必经点
        size_t n = bigr.net.vertexs.size();
        basic_string<bool> vs; vs.resize(n);
        auto dfs = [&](auto &&slf, size_t u, bool w) -> void {
            if (vs[u])return;
            vs[u] = 1;
            for (size_t id : bigr.net.vertexs[u])
                if (bigr.net.edges[id].flow == w)
                    slf(slf, bigr.net.edges[id].to, w);
        };
        vector<size_t> r;
        dfs(dfs, bigr.net.source, 1);// 从源点出发走流量等于 $1$ 的边所不能到达的左部点
        for (size_t i = 0; i < bigr.left; ++i)if (!vs[i])r.emplace_back(i);
        fill(vs.begin(), vs.end(), false);
        dfs(dfs, bigr.net.sink, 0);// 从汇点出发走流量等于 $0$ 的边所不能到达的右部点
        for (size_t i = 0; i < bigr.right; ++i)if (!vs[bigr.left + i])r.emplace_back(bigr.left + i);
        return r;
    }

    struct network_no_source_sink_with_bound {
        network net;
        size_t vsource, vsink;
        flow_t base;
        vector<signed_flow_t> in;
        network_no_source_sink_with_bound() : net{}, vsource{}, vsink{}, base{}, in{} {}
        #ifdef bound_flow_less_edge
        bool built;
        #endif
        void set_vertex(size_t n){
            vsource = n, vsink = n + 1;
            net.set_vertex(n + 2, vsource, vsink);
            in.assign(n + 2, 0);
            base = 0;
            #ifdef bound_flow_less_edge
            built = false;
            #endif
        }
        void clear(){
            set_vertex(0);
        }
        void reset_flow(){
            net.reset_flow();
        }
        #ifdef bound_flow_less_edge
        void add_edge(size_t from, size_t to, flow_t low, flow_t high){
            if (!__builtin_expect(low <= high, true))
                throw runtime_error("network_no_source_sink_with_bound::add_edge : The lower bound is higher than the upper bound.");
            if (high != low)net.add_edge(from, to, high - low);
            if (low){
                in[from] -= low;
                in[to] += low;
                // net.add_edge(from, vsink, low);
                // net.add_edge(vsource, to, low);
            }
        }
        void add_edge_fixed(size_t from, size_t to, flow_t fixed_flow){
            add_edge(from, to, fixed_flow, fixed_flow);
        }
        void add_edge_norm(size_t from, size_t to, flow_t flow = 1){
            add_edge(from, to, 0, flow);
        }
        void build(){
            base = 0;
            for (size_t i = 0, _ = net.vertexs.size(); i < _; ++i){
                if (in[i] < 0)net.add_edge(i, vsink, -in[i]);
                if (in[i] > 0)net.add_edge(vsource, i, in[i]), base += in[i];
            }
        }
        #else
        void add_edge_nobuild(size_t from, size_t to, flow_t low, flow_t high){//无需调用 build
            if (!__builtin_expect(low <= high, true))
                throw runtime_error("network_no_source_sink_with_bound::add_edge_nobuild : The lower bound is higher than the upper bound.");
            if (high != low)net.add_edge(from, to, high - low);
            if (low){
                net.add_edge(from, vsink, low);
                net.add_edge(vsource, to, low);
                base += low;
            }
        }
        #endif
        bool exists_flow(){
            #ifdef bound_flow_less_edge
            assert(built);
            #endif
            return net.DINIC_max_flow() == base;
        }
    };

    struct network_with_bound {
        network net;
        size_t vsource, vsink;
        size_t source, sink;
        flow_t base;
        vector<signed_flow_t> in;
        network_with_bound() : net{}, vsource{}, vsink{}, source{}, sink{}, base{}, in{} {}
        #ifdef bound_flow_less_edge
        bool built;
        #endif
        void set_vertex(size_t n, size_t S, size_t T){
            source = S, sink = T;
            vsource = n, vsink = n + 1;
            net.set_vertex(n + 2, vsource, vsink);
            in.assign(n + 2, 0);
            base = 0;
            net.add_edge(T, S, flow_max_v);
            #ifdef bound_flow_less_edge
            built = false;
            #endif
        }
        void clear(){
            set_vertex(0, 0, 0);
        }
        void reset_flow(){
            net.reset_flow();
        }
        #ifdef bound_flow_less_edge
        void add_edge(size_t from, size_t to, flow_t low, flow_t high){
            if (!__builtin_expect(low <= high, true))
                throw runtime_error("network_with_bound::add_edge : The lower bound is higher than the upper bound.");
            if (high != low)net.add_edge(from, to, high - low);
            if (low){
                in[from] -= low;
                in[to] += low;
                // net.add_edge(from, vsink, low);
                // net.add_edge(vsource, to, low);
            }
        }
        void add_edge_fixed(size_t from, size_t to, flow_t fixed_flow){
            add_edge(from, to, fixed_flow, fixed_flow);
        }
        void add_edge_norm(size_t from, size_t to, flow_t flow = 1){
            add_edge(from, to, 0, flow);
        }
        void build(){
            base = 0;
            for (size_t i = 0, _ = net.vertexs.size(); i < _; ++i){
                if (in[i] < 0)net.add_edge(i, vsink, -in[i]);
                if (in[i] > 0)net.add_edge(vsource, i, in[i]), base += in[i];
            }
            built = true;
        }
        #else
        void add_edge_nobuild(size_t from, size_t to, flow_t low, flow_t high){//无需调用 build
            if (!__builtin_expect(low <= high, true))
                throw runtime_error("network_with_bound::add_edge_nobuild : The lower bound is higher than the upper bound.");
            if (high != low)net.add_edge(from, to, high - low);
            if (low){
                net.add_edge(from, vsink, low);
                net.add_edge(vsource, to, low);
                base += low;
            }
        }
        #endif
        bool exists_flow(){
            #ifdef bound_flow_less_edge
            assert(built);
            #endif
            return net.DINIC_max_flow() == base;
        }
        pair<bool, flow_t> max_flow(){//(exists, flow)
            #ifdef bound_flow_less_edge
            assert(built);
            #endif
            if (!exists_flow())return make_pair(false, 0);
            flow_t fst = net.edges[1].flow;
            net.source = source, net.sink = sink;
            net.edges[0].flow = net.edges[1].flow = 0;
            return make_pair(true, fst + net.DINIC_max_flow());
        }
        pair<bool, flow_t> min_flow(){//(exists, flow)
            #ifdef bound_flow_less_edge
            assert(built);
            #endif
            if (!exists_flow())return make_pair(false, 0);
            flow_t fst = net.edges[1].flow;
            net.source = sink, net.sink = source;
            net.edges[0].flow = net.edges[1].flow = 0;
            return make_pair(true, fst - net.DINIC_max_flow());
        }
    };

    struct network_with_cost_and_bound {
        network_with_cost net;
        size_t vsource, vsink;
        size_t source, sink;
        flow_t base_flow;
        cost_t base_cost;
        vector<signed_flow_t> in;
        network_with_cost_and_bound() : net{}, vsource{}, vsink{}, source{}, sink{}, base_flow{}, base_cost{}, in{} {}
        #ifdef bound_flow_less_edge
        bool built;
        #endif
        void set_vertex(size_t n, size_t S, size_t T){
            source = S, sink = T;
            vsource = n, vsink = n + 1;
            net.set_vertex(n + 2, vsource, vsink);
            in.assign(n + 2, 0);
            base_flow = 0;
            base_cost = 0;
            net.add_edge(T, S, flow_max_v, 0);
            #ifdef bound_flow_less_edge
            built = false;
            #endif
        }
        void clear(){
            set_vertex(0, 0, 0);
        }
        void reset_flow(){
            net.reset_flow();
        }
        #ifdef bound_flow_less_edge
        void add_edge(size_t from, size_t to, flow_t low, flow_t high, cost_t cs){
            if (!__builtin_expect(low <= high, true))
                throw runtime_error("network_with_cost_and_bound::add_edge : The lower bound is higher than the upper bound.");
            if (high != low)net.add_edge(from, to, high - low, cs);
            if (low){
                in[from] -= low;
                in[to] += low;
                // net.add_edge(from, vsink, low, 0);
                // net.add_edge(vsource, to, low, 0);
                base_cost += low * cs;
            }
        }
        void add_edge_fixed(size_t from, size_t to, flow_t fixed_flow, cost_t cs = 0){
            add_edge(from, to, fixed_flow, fixed_flow, cs);
        }
        void add_edge_norm(size_t from, size_t to, flow_t flow = 1, cost_t cs = 0){
            add_edge(from, to, 0, flow, cs);
        }
        void build(){
            base_flow = 0;
            for (size_t i = 0, _ = net.vertexs.size(); i < _; ++i){
                if (in[i] < 0)net.add_edge(i, vsink, -in[i], 0);
                if (in[i] > 0)net.add_edge(vsource, i, in[i], 0), base_flow += in[i];
            }
            built = true;
        }
        #else
        void add_edge_nobuild(size_t from, size_t to, flow_t low, flow_t high, cost_t cs){//无需调用 build
            if (!__builtin_expect(low <= high, true))
                throw runtime_error("network_with_cost_and_bound::add_edge_nobuild : The lower bound is higher than the upper bound.");
            if (high != low)net.add_edge(from, to, high - low, cs);
            if (low){
                net.add_edge(from, vsink, low, 0);
                net.add_edge(vsource, to, low, 0);
                base_cost += low * cs;
                base_flow += low;
            }
        }
        #endif
        pair<bool, cost_t> min_cost(){//feasible flow
            #ifdef bound_flow_less_edge
            assert(built);
            #endif
            cost_and_flow res = net.EK_min_cost();
            if (res.flow != base_flow)return make_pair(false, 0);
            net.source = source, net.sink = sink;
            net.edges[0].flow = net.edges[1].flow = 0;
            return make_pair(true, res.cost + net.EK_min_cost(false).cost);
        }
        pair<bool, cost_t> max_cost(){//feasible flow
            #ifdef bound_flow_less_edge
            assert(built);
            #endif
            cost_and_flow res = net.EK_max_cost();
            if (res.flow != base_flow)return make_pair(false, 0);
            net.source = source, net.sink = sink;
            net.edges[0].flow = net.edges[1].flow = 0;
            return make_pair(true, res.cost + net.EK_max_cost(false).cost);
        }
    };

}

#include <bits/stdc++.h>
using namespace std;
int n;
vector<int> r[100010];
int mt[100010];
bool md[100010];
bool mtd[100010];
pair<int, int> ed[100010];
int main(){
    ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
    cin >> n;
    vector<flow_algo::edge_without_weight> edg;
    for (int i = 1, c, x; i < n; ++i){
        cin >> c;
        while (c--){
            int x;
            cin >> x;
            r[x].emplace_back(i);
            edg.emplace_back(x - 1, i - 1);
        }
    }
    auto G = flow_algo::bipartite_graph(n, n - 1, edg.begin(), edg.end());
    auto mtc = flow_algo::max_match_flow(G);
    if (mtc.size() < n - 1){
        cout << -1 << "\n";
        return 0;
    }
    for (auto [l, r] : mtc)mt[r + 1] = l + 1, mtd[l + 1] = 1;
    int ct = 0;
    auto dfs = [&](auto &&slf, int u) -> void {
        for (int v : r[u])if (!md[v]){
            md[v] = 1;
            ++ct;
            ed[v] = {u, mt[v]};
            slf(slf, mt[v]);
        }
    };
    dfs(dfs, find(mtd + 1, mtd + n + 1, 0) - mtd);
    if (ct != n - 1)cout << -1 << "\n";
    else for (int i = 1; i < n; ++i)cout << ed[i].first << " " << ed[i].second << "\n";
    return 0;
}

提出情報

提出日時
問題 F - Construction of a tree
ユーザ szt100309
言語 C++23 (GCC 15.2.0)
得点 2200
コード長 34261 Byte
結果 AC
実行時間 618 ms
メモリ 41732 KiB

コンパイルエラー

./Main.cpp: In function 'int main()':
./Main.cpp:819:24: warning: unused variable 'x' [-Wunused-variable]
  819 |     for (int i = 1, c, x; i < n; ++i){
      |                        ^
./Main.cpp:830:20: warning: comparison of integer expressions of different signedness: 'std::vector<flow_algo::edge_without_weight>::size_type' {aka 'long unsigned int'} and 'int' [-Wsign-compare]
  830 |     if (mtc.size() < n - 1){
      |         ~~~~~~~~~~~^~~~~~~

ジャッジ結果

セット名 Sample All
得点 / 配点 0 / 0 2200 / 2200
結果
AC × 3
AC × 73
セット名 テストケース
Sample sample01.txt, sample02.txt, sample03.txt
All sample01.txt, sample02.txt, sample03.txt, in01.txt, in02.txt, in03.txt, in04.txt, in05.txt, in06.txt, in07.txt, in08.txt, in09.txt, in10.txt, in11.txt, in12.txt, in13.txt, in14.txt, in15.txt, in16.txt, in17.txt, in18.txt, in19.txt, in20.txt, in21.txt, in22.txt, in23.txt, in24.txt, in25.txt, in26.txt, in27.txt, in28.txt, in29.txt, in30.txt, in31.txt, in32.txt, in33.txt, in34.txt, in35.txt, in36.txt, in37.txt, in38.txt, in39.txt, in40.txt, in41.txt, in42.txt, in43.txt, in44.txt, in45.txt, in46.txt, in47.txt, in48.txt, in49.txt, in50.txt, in51.txt, in52.txt, in53.txt, in54.txt, in55.txt, in56.txt, in57.txt, in58.txt, in59.txt, in60.txt, in61.txt, in62.txt, in63.txt, in64.txt, in65.txt, in66.txt, in67.txt, sample01.txt, sample02.txt, sample03.txt
ケース名 結果 実行時間 メモリ
in01.txt AC 158 ms 37488 KiB
in02.txt AC 17 ms 7260 KiB
in03.txt AC 148 ms 37432 KiB
in04.txt AC 33 ms 9940 KiB
in05.txt AC 62 ms 32712 KiB
in06.txt AC 258 ms 31492 KiB
in07.txt AC 511 ms 31596 KiB
in08.txt AC 498 ms 32372 KiB
in09.txt AC 582 ms 32948 KiB
in10.txt AC 26 ms 16248 KiB
in11.txt AC 58 ms 16640 KiB
in12.txt AC 84 ms 12708 KiB
in13.txt AC 88 ms 17196 KiB
in14.txt AC 106 ms 16696 KiB
in15.txt AC 9 ms 7136 KiB
in16.txt AC 24 ms 7400 KiB
in17.txt AC 26 ms 7860 KiB
in18.txt AC 30 ms 8144 KiB
in19.txt AC 36 ms 8516 KiB
in20.txt AC 51 ms 39756 KiB
in21.txt AC 84 ms 41732 KiB
in22.txt AC 579 ms 39272 KiB
in23.txt AC 43 ms 12408 KiB
in24.txt AC 60 ms 16936 KiB
in25.txt AC 87 ms 17832 KiB
in26.txt AC 69 ms 17028 KiB
in27.txt AC 76 ms 17504 KiB
in28.txt AC 87 ms 17772 KiB
in29.txt AC 48 ms 12664 KiB
in30.txt AC 56 ms 13084 KiB
in31.txt AC 25 ms 7812 KiB
in32.txt AC 22 ms 8188 KiB
in33.txt AC 30 ms 8628 KiB
in34.txt AC 23 ms 7436 KiB
in35.txt AC 21 ms 8004 KiB
in36.txt AC 25 ms 7336 KiB
in37.txt AC 18 ms 7032 KiB
in38.txt AC 21 ms 7136 KiB
in39.txt AC 23 ms 7320 KiB
in40.txt AC 21 ms 7152 KiB
in41.txt AC 231 ms 31236 KiB
in42.txt AC 317 ms 31328 KiB
in43.txt AC 323 ms 32140 KiB
in44.txt AC 243 ms 31756 KiB
in45.txt AC 270 ms 32440 KiB
in46.txt AC 318 ms 32388 KiB
in47.txt AC 289 ms 31632 KiB
in48.txt AC 305 ms 32052 KiB
in49.txt AC 77 ms 32616 KiB
in50.txt AC 78 ms 32616 KiB
in51.txt AC 83 ms 32832 KiB
in52.txt AC 164 ms 32660 KiB
in53.txt AC 152 ms 32704 KiB
in54.txt AC 149 ms 32584 KiB
in55.txt AC 170 ms 32832 KiB
in56.txt AC 172 ms 32672 KiB
in57.txt AC 1 ms 3556 KiB
in58.txt AC 1 ms 3544 KiB
in59.txt AC 148 ms 37660 KiB
in60.txt AC 171 ms 31192 KiB
in61.txt AC 37 ms 16948 KiB
in62.txt AC 488 ms 38388 KiB
in63.txt AC 174 ms 31680 KiB
in64.txt AC 177 ms 31280 KiB
in65.txt AC 376 ms 33064 KiB
in66.txt AC 375 ms 24008 KiB
in67.txt AC 618 ms 31304 KiB
sample01.txt AC 1 ms 3808 KiB
sample02.txt AC 1 ms 3656 KiB
sample03.txt AC 1 ms 3584 KiB