Cod sursa(job #3189882)

Utilizator annna7Pecheanu Anna annna7 Data 6 ianuarie 2024 16:58:17
Problema Cuplaj maxim in graf bipartit Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 2.9 kb
#include <vector>
#include <queue>
#include <climits>
#include <fstream>
#define NIL 0

using namespace std;

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

struct Edge {
    int to;
    int flow;
    int capacity;
    int reverse;
};

class HopkroftKarp {
    int N, M;
    vector<int> rightCorrespondent, leftCorrespondent, level;
    vector<vector<int>> adj;
public:
    HopkroftKarp(int N, int M);
    void addEdge(int u, int v);
    bool bfs();
    bool dfs(int leftNode);
    int hopkroft();
    void printMatches();
};

HopkroftKarp::HopkroftKarp(int n, int m) : N(n), M(m), leftCorrespondent(n + 1), rightCorrespondent(m + 1), level(n + 1), adj(n + 1) {}

void HopkroftKarp::addEdge(int u, int v) {
    adj[u].push_back(v);
}

bool HopkroftKarp::bfs() {
    queue<int> q;
    level.assign(N + 1, INT_MAX);

    // add unmatched first layer vertices
    for (int i = 1; i <= N; ++i) {
        if (rightCorrespondent[i] == NIL) {
            level[i] = 0;
            q.emplace(i);
        }
    }

    while (!q.empty()) {
        int leftNode = q.front();
        q.pop();

        // found unmatched left vertex
        if (leftNode == NIL) {
            break;
        }

        for (auto &rightNode: adj[leftNode]) {
            if (level[leftCorrespondent[rightNode]] == INT_MAX) {
                level[leftCorrespondent[rightNode]] = level[leftNode] + 1;
                q.emplace(leftCorrespondent[rightNode]);
            }
        }
    }

    // this means that an unmatched left vertex was reached, which is what we want
    return level[NIL] != INT_MAX;
}

bool HopkroftKarp::dfs(int leftNode) {
    if (leftNode == NIL) {
        return true;
    }

    for (auto &rightNode: adj[leftNode]) {
        if (level[leftCorrespondent[rightNode]] == level[leftNode] + 1 && dfs(leftCorrespondent[rightNode])) {
            rightCorrespondent[leftNode] = rightNode;
            leftCorrespondent[rightNode] = leftNode;
            return true;
        }
    }

    // TODO
    level[leftNode] == INT_MAX;
    return false;
}

int HopkroftKarp::hopkroft() {
    leftCorrespondent.assign(M + 1, NIL);
    rightCorrespondent.assign(N + 1, NIL);

    int answer = 0;
    while (bfs()) {
        for (int i = 1; i <= N; ++i) {
            if (rightCorrespondent[i] == NIL && dfs(i)) {
                answer++;
            }
        }
    }

    return answer;
}

void HopkroftKarp::printMatches() {
    for (int i = 1; i <= N; ++i) {
        if (rightCorrespondent[i] != NIL) {
            fout << i << " " << rightCorrespondent[i] << endl;
        }
    }
}

int main()
{
    int N, M, E, x, y;
    fin >> N >> M >> E;

    HopkroftKarp algorithm(N, M);
    while (E--) {
        fin >> x >> y;
        algorithm.addEdge(x, y);
    }

    fout << algorithm.hopkroft() << endl;
    algorithm.printMatches();
    return 0;
}