Cod sursa(job #3220380)

Utilizator AleXutzZuDavid Alex Robert AleXutzZu Data 3 aprilie 2024 13:29:11
Problema Cuplaj maxim in graf bipartit Scor 50
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.07 kb
#include <iostream>
#include <vector>
#include <queue>
#include <algorithm>

struct Network {
private:
    std::vector<std::vector<int>> adj;
    std::vector<std::vector<int>> capacity;
    std::vector<std::vector<int>> flows;
    std::vector<int> parent;
    std::vector<bool> group;
    int size;

    void mark_group(int node) {
        group[node] = true;
        for (const auto &x: adj[node]) {
            if (capacity[node][x] <= 0) continue;
            if (group[x]) continue;
            mark_group(x);
        }
    }

    int augment(int source, int target) {
        parent.assign(size + 1, -1);
        parent[source] = -2;

        std::queue<std::pair<int, int>> queue;
        queue.emplace(source, 1e9);

        while (!queue.empty()) {
            auto [node, flow] = queue.front();
            queue.pop();

            for (const auto &x: adj[node]) {
                if (parent[x] == -1 && capacity[node][x]) {
                    parent[x] = node;
                    int new_flow = std::min(flow, capacity[node][x]);
                    if (x == target) return new_flow;
                    queue.emplace(x, new_flow);
                }
            }
        }
        return 0;
    }

public:
    explicit Network(int size) : size(size) {
        adj.resize(size + 1);
        group.resize(size + 1, false);
        capacity.resize(size + 1, std::vector<int>(size + 1, 0));
        flows.resize(size + 1, std::vector<int>(size + 1, 0));
    }

    void add_edge(int x, int y, int cap) {
        adj[x].push_back(y);
        adj[y].push_back(x);
        capacity[x][y] = cap;
    }

    int max_flow(int source, int target) {
        int ans = 0;

        int flow = augment(source, target);
        while (flow != 0) {
            ans += flow;

            int node = target;
            while (node != source) {
                int p = parent[node];
                capacity[p][node] -= flow;
                flows[p][node] += flow;
                capacity[node][p] += flow;
                flows[node][p] -= flow;
                node = p;
            }

            flow = augment(source, target);
        }
        return ans;
    }

    std::vector<std::vector<int>> get_flow() {
        return flows;
    }
};

int main() {
    freopen("cuplaj.in", "r", stdin);
    freopen("cuplaj.out", "w", stdout);
    std::ios_base::sync_with_stdio(false);
    std::cin.tie(nullptr);
    std::cout.tie(nullptr);

    int n, m, k;
    std::cin >> n >> m >> k;

    Network network(n + m + 1);

    for (int i = 1; i <= n; ++i) network.add_edge(0, i, 1);
    for (int i = 1; i <= m; ++i) network.add_edge(n + i, n + m + 1, 1);

    while (k--) {
        int x, y;
        std::cin >> x >> y;
        network.add_edge(x, n + y, 1);
    }

    std::cout << network.max_flow(0, n + m + 1) << '\n';
    auto flow = network.get_flow();

    for (int i = 1; i <= n; ++i) {
        for (int j = 1; j <= m; ++j) {
            if (flow[i][n + j]) std::cout << i << " " << j << '\n';
        }
    }
    return 0;
}