Cod sursa(job #2962193)

Utilizator Marius_TillingerTillinger Marius Marius_Tillinger Data 7 ianuarie 2023 22:22:32
Problema Cuplaj maxim in graf bipartit Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.38 kb
#include <iostream>
#include <fstream>
#include <vector>
#include <queue>

using namespace std;

// Declare input and output files
ifstream fin("cuplaj.in");
ofstream fout("cuplaj.out");

int leftSize, rightSize, edges, source, sink;

vector<bool> existingRight;
vector<pair<int, int>> parent;
vector<pair<int, int>> rightNodes;
vector<vector<pair<int, pair<int, int>>>> adjacency;
queue<int> q;

void addEdge(int u, int v) {
    adjacency[u].push_back({v, {1, adjacency[v].size()}});
    adjacency[v].push_back({u, {0, adjacency[u].size() - 1}});
    if (v == sink)
        rightNodes.emplace_back(u, adjacency[u].size() - 1);
}

bool bfs() {
    vector<bool> visited(sink + 1);
    q.push(source);
    visited[source] = true;
    parent[source] = {-1, -1};

    while (!q.empty()) {
        int currentNode = q.front();
        q.pop();
        if (currentNode == sink) continue;

        int c = 0;
        for (auto node: adjacency[currentNode]) {
            int a, b;
            a = node.first;
            b = node.second.first;
            if (!visited[a] && b) {
                parent[a] = {currentNode, c};
                visited[a] = true;
                q.push(a);
            }
            c++;
        }
    }
    return visited[sink];
}

long int maxFlow() {

    long int max_flow = 0;

    while (bfs()) {
        for (auto node: rightNodes) {
            int u, v, x, y, min_path = 1;
            parent[sink] = node;
            v = sink;
            // Trace the path back to the source
            while (parent[v].first != -1) {
                u = parent[v].first;
                x = parent[v].second;
                // Update the minimum path capacity
                min_path = min(min_path, adjacency[u][x].second.first);
                v = u;
            }
            // Update the capacities of the edges and the reverse edges along the path
            v = sink;
            while (parent[v].first != -1) {
                u = parent[v].first;
                x = parent[v].second;
                y = adjacency[u][x].second.second;
                adjacency[u][x].second.first -= min_path;
                adjacency[v][y].second.first += min_path;
                v = u;
            }
            // Increase the maximum flow by the minimum path capacity
            max_flow += min_path;
        }
    }
    return max_flow;
}

int main() {

    fin >> leftSize >> rightSize >> edges;

    source = 0;
    sink = leftSize + rightSize + 1;

    existingRight.resize(rightSize + 1);
    parent.resize(sink + 1);
    adjacency.resize(sink + 1);
    
    for (int i = 1; i <= leftSize; i++)
        addEdge(source, i);

    for (int i = 1; i <= edges; i++) {
        int u, v;
        fin >> u >> v;
        addEdge(u, leftSize + v);
        existingRight[v] = true;
    }

    // Add edges from each node on the right side that has an incoming edge to the sink
    for (int i = 1; i <= rightSize; i++) {
        if (existingRight[i])
            addEdge(leftSize + i, sink);
    }

    fout << maxFlow() << '\n';
    for (int u = 1; u <= leftSize; u++)
        for (auto node: adjacency[u]) {
            int v, c;
            v = node.first;
            c = node.second.first;
            if (v && c == 0 && v != sink)
                fout << u << " " << v - leftSize << '\n';
        }
    return 0;
}