Cod sursa(job #3121853)

Utilizator patrixKovacs Patrik patrix Data 15 aprilie 2023 18:05:27
Problema Cuplaj maxim in graf bipartit Scor 60
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 2.94 kb
// https://www.infoarena.ro/problema/cuplaj

#include <fstream>
#include <vector>
#include <array>
#include <list>
#include <algorithm>

std::ifstream in("cuplaj.in");
std::ofstream out("cuplaj.out");


struct Node {
    struct Edge {
        Node* from;
        Node* to;
        bool matched = false;

        Edge(Node* from, Node* to): from(from), to(to) {}
    };

    Node() = default;
    Node(const int id, const bool main): id(id) {}

    int id;
    std::vector<Edge> edges = std::vector<Edge>();
    Edge* matched = nullptr;
};

struct EdgeRef {
    Node::Edge* edge;
    EdgeRef* back_ref;

    EdgeRef(Node::Edge* edge, EdgeRef* back_ref)
        : edge(std::move(edge))
        , back_ref(std::move(back_ref)) {}
};

void bfs(Node& start_node) {
    if (start_node.matched) {
        return;
    }
    std::list<EdgeRef> res;
    std::transform(start_node.edges.begin(), start_node.edges.end(), std::inserter(res, res.end()), [](auto& edge) -> EdgeRef { 
        return {&edge, nullptr}; 
    });

    auto it = res.begin();
    bool finished = false;
    while (it != res.end()) {
        if (it->edge->to->matched == nullptr) {
            finished = true;
            break;
        }
        for (auto& edge: it->edge->to->edges) {
            if (edge.matched != it->edge->matched && std::find_if(res.begin(), res.end(), [&edge](const auto& edge_ref) {
                return edge_ref.edge == &edge;
            }) == res.end()) {
                res.emplace_back(&edge, &(*it));
            }
        }
        ++it;
    }
    if (finished) {
        auto ptr = &(*it);
        while (ptr != nullptr) {
            ptr->edge->matched = !ptr->edge->matched;
            const auto pos = std::find_if(ptr->edge->to->edges.begin(), ptr->edge->to->edges.end(), [&ptr](const auto& edge) {
                return edge.to == ptr->edge->from;
            });
            pos->matched = ptr->edge->matched;
            if (ptr->edge->matched) {
                ptr->edge->from->matched = ptr->edge;
                ptr->edge->to->matched = &(*pos);
            } else {
                ptr->edge->from->matched = nullptr;
            }
            ptr = ptr->back_ref;
        }
    }
}

int main() {
    int n, m, e;
    in >> n >> m >> e;
    std::vector<Node> nodes_a(n), nodes_b(m);
    for (int i = 1; i <= n; ++i) {
        nodes_a[i-1] = Node(i, true);
    }
    for (int i = 1; i <= m; ++i) {
        nodes_b[i-1] = Node(i, false);
    }
    int a, b;
    for (int i = 0; i < e; ++i) {
        in >> a >> b;
        nodes_a[a-1].edges.emplace_back(&nodes_a[a-1], &nodes_b[b-1]);
        nodes_b[b-1].edges.emplace_back(&nodes_b[b-1], &nodes_a[a-1]);
    }

    int count = 0;
    for (auto& node: nodes_a) {
        bfs(node);
        if (node.matched != nullptr) {
            ++count;
        }
    }

    out << count << '\n';
    for (const auto& node: nodes_a) {
        if (node.matched != nullptr) {
            out << node.id << ' ' << node.matched->to->id << '\n';
        }
    }


}