Cod sursa(job #2462671)

Utilizator preda.andreiPreda Andrei preda.andrei Data 27 septembrie 2019 18:44:24
Problema Cuplaj maxim in graf bipartit Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 2.08 kb
#include <fstream>
#include <vector>

using namespace std;

struct Node
{
    vector<int> edges;
    int pair = -1;
};

using Graph = vector<Node>;
using BipartiteGraph = pair<Graph, Graph>;

bool FindPair(BipartiteGraph &g, int node, vector<bool> &used)
{
    if (used[node]) {
        return false;
    }
    used[node] = true;

    for (const auto &next : g.first[node].edges) {
        if (g.second[next].pair == -1) {
            g.second[next].pair = node;
            g.first[node].pair = next;
            return true;
        }
    }

    for (const auto &next : g.first[node].edges) {
        if (FindPair(g, g.second[next].pair, used)) {
            g.second[next].pair = node;
            g.first[node].pair = next;
            return true;
        }
    }
    return false;
}

vector<pair<int, int>> ExtractMatching(const BipartiteGraph &g)
{
    vector<pair<int, int>> matching;
    for (const auto &node : g.first) {
        if (node.pair == -1) {
            continue;
        }

        int right = node.pair;
        int left = g.second[right].pair;
        matching.push_back({left, right});
    }
    return matching;
}

vector<pair<int, int>> FindMatching(BipartiteGraph &g)
{
    auto done = false;
    while (!done) {
        done = true;

        vector<bool> used(g.first.size(), false);
        for (size_t i = 0; i < g.first.size(); i += 1) {
            if (g.first[i].pair == -1 && FindPair(g, i, used)) {
                done = false;
            }
        }
    }
    return ExtractMatching(g);
}

int main()
{
    ifstream fin("cuplaj.in");
    ofstream fout("cuplaj.out");

    int nodes1, nodes2, edges;
    fin >> nodes1 >> nodes2 >> edges;

    BipartiteGraph graph = {Graph(nodes1), Graph(nodes2)};
    for (int i = 0; i < edges; i += 1) {
        int a, b;
        fin >> a >> b;
        graph.first[a - 1].edges.push_back({b - 1});
        graph.second[b - 1].edges.push_back({a - 1});
    }

    auto matching = FindMatching(graph);
    fout << matching.size() << "\n";

    for (const auto &p : matching) {
        fout << p.first + 1 << " " << p.second + 1 << "\n";
    }

    return 0;
}