Cod sursa(job #2960729)

Utilizator 0SiSBesliu Radu-Stefan 0SiS Data 4 ianuarie 2023 21:29:09
Problema Cuplaj maxim in graf bipartit Scor 0
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.2 kb
#include <iostream>
#include <fstream>
#include <list>
#include <vector>
#include <queue>

using namespace std;

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

int leftNodesNumber, rightNodesNumber;
int edges, s, t;
vector < bool > existingRight;
vector < pair < int, int >> parent, rightNodes;
vector < vector < tuple < int, int, int >>> adjList;

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) {
        rightNodes.emplace_back(x, adjList[x].size() - 1);
    }
}

bool bfs() {
    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& node: adjList[firstInQueue]) {
            auto [adjNode, capacity, reverseEdge] = node;

            if (!visited[adjNode] && capacity) {
                parent[adjNode] = {firstInQueue, i};
                visited[adjNode] = true;
                q.push(adjNode);
            }

            ++i;
        }
    }

    return visited[t];
}

long long cuplaj() {
    long long maxFlow = 0;

    while (bfs()) {
        for (auto const& node: rightNodes) {
            int currentFlow = 1;
            parent[t] = node;
            int y = t;
            while (parent[y].first != -1) {
                int first = parent[y].first;
                int second = parent[y].second;
                currentFlow = min(currentFlow, get < 0 > (adjList[first][second]));
                y = second;
            }

            y = t;
            while (parent[y].first != -1) {
                int u = parent[y].first;
                int v = parent[y].second;
                int w = get < 2 > (adjList[u][v]);
                auto [adjNode, capacity, reverseEdge] = adjList[u][v];
                auto [adjNode2, capacity2, reverseEdge2] = adjList[y][w];
                adjList[u][v] = {adjNode, capacity - currentFlow, reverseEdge};
                adjList[y][w] = {adjNode2, capacity2 + currentFlow, reverseEdge2};
                y = u;
            }
            maxFlow += currentFlow;
        }
    }
    return maxFlow;
}

int main() {
    f >> leftNodesNumber >> rightNodesNumber >> edges;
    t = leftNodesNumber + rightNodesNumber + 1;
    existingRight.resize(rightNodesNumber + 1);
    parent.resize(t + 1);
    adjList.resize(t + 1);
    for (int i = 1; i <= leftNodesNumber; ++i) {
        createEdge(s, i);
    }

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

    for (int i = 1; i <= rightNodesNumber; ++i) {
        if (existingRight[i]) {
            createEdge(leftNodesNumber + i, t);
        }
    }

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