Cod sursa(job #2961107)

Utilizator 0SiSBesliu Radu-Stefan 0SiS Data 5 ianuarie 2023 20:01:58
Problema Cuplaj maxim in graf bipartit Scor 24
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.08 kb
#include <iostream>
#include <fstream>
#include <list>
#include <vector>
#include <tuple>
#include <queue>

using namespace std;

ifstream f("cuplaj.in");
ofstream g("cuplaj.out");

int sizeLeft, sizeRight, edges;
int s, t;

vector < vector < tuple < int, int, int >>> adjList;
vector < bool > inRight;
vector < pair < int, int >> nodesRight;
vector < pair < int, int >> parent;

void createEdge(int x, int y) {
    adjList[x].emplace_back(y, 1, adjList[y].size());
    adjList[y].emplace_back(x, 0, adjList[x].size() - 1);
    
    if (y == t) {
        nodesRight.emplace_back(x, adjList[x].size()-1);
    }
}

bool bf() {
    vector < bool > visited(t + 1);
    queue < int > q;
    
    q.push(s);
    visited[s] = true;
    parent[s] = {-1, -1};

    while (!q.empty()) {
        int firstInQueue = q.front();
        q.pop();
        
        if (firstInQueue == t) {
            continue;
        }

        int i = 0;
        for (auto const& adjNode: adjList[firstInQueue]) {
            auto [node, capacity, rev] = adjNode;

            if (!visited[node] && capacity) {
                parent[node]= {firstInQueue, i};
                visited[node] = true;

                q.push(node);
            }

            ++i;
        }
    }

    return visited[t];
}

long long int cuplaj() {
    long long int maxFlow = 0;
    
    while (bf()) {
        for (auto const& node: nodesRight) {
            int currentFlow = 1;
            parent[t] = node;
            int y = t;
            
            while (parent[y].first != -1) {
                int first = parent[y].first;
                int second = parent[y].second;
                auto [_node, capacity, rev] = adjList[first][second];

                currentFlow = min(currentFlow, capacity);
                y = first;
            }
            y = t;

            while (parent[y].first != -1) {
                int first = parent[y].first;
                int second = parent[y].second;
                auto [_node, capacity, rev] = adjList[first][second];

                adjList[first][second] = {_node, capacity - currentFlow, rev};
                adjList[_node][rev] = {first, capacity + currentFlow, second};

                y = first;
            }

            maxFlow += currentFlow;
        }
    }

    return maxFlow;
}

int main() {
    f >> sizeLeft >> sizeRight >> edges;

    t = sizeLeft + sizeRight + 1;
    inRight.resize(sizeRight + 1);
    parent.resize(t + 1);
    adjList.resize(t + 1);

    for (int i = 1; i <= sizeLeft; ++i) {
        createEdge(s, i);
    }

    for (int i = 1; i <= edges; ++i) {
        int x, y;
        f >> x >> y;
        createEdge(x, sizeLeft + y);
        inRight[y] = true;
    }

    for (int i = 1; i <= sizeRight; ++i) {
        if (inRight[i]) {
            createEdge(sizeLeft + i, t);
        }
    }

    g << cuplaj() << '\n';
    for (int i = 1; i <= sizeLeft; ++i) {
        for (auto const& adjNode: adjList[i]) {
            int v, c;
            auto [node, capacity, rev] = adjNode;
            if (node && capacity == 0 && node != t)
                g << i << " " << node - sizeLeft << '\n';
        }
    }
}