Cod sursa(job #3266222)

Utilizator stefan0211Tacu Darius Stefan stefan0211 Data 6 ianuarie 2025 17:14:07
Problema Cuplaj maxim in graf bipartit Scor 50
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 2.65 kb
#include <iostream>
#include <fstream>
#include <vector>
#include <queue>
#include <climits>
using namespace std;

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

int n, m, s, t, e, flux_initial = 0;

vector<vector<int>> la;
vector<vector<int>> capacitate, flux;
vector<int> tata;

void Read()
{
    // fie s = 0 si t = n + m + 1
    f >> n >> m >> e;
    s = 0;
    t = n + m + 1;

    la.resize(n + m + 2);
    capacitate.resize(n + m + 2, vector<int>(n + m + 2, 0));

    // INIȚIALIZĂM FLUXUL NUL
    flux.resize(n + m + 2, vector<int>(n + m + 2, 0));

    tata.resize(n + m + 2, -1);

    int x, y;
    for (int i = 1; i <= e; i++)
    {
        f >> x >> y;
        la[x].push_back(n + y);
        la[n + y].push_back(x);
        capacitate[x][n + y] = 1;
    }

    // initializam la[s] cu muchiile corespunzătoare
    for (size_t i = 1; i <= n; i++)
    {
        la[s].push_back(i);
        // flux[s][i] = 1;
        capacitate[s][i] = 1;
    }
    for (size_t i = n + 1; i <= n + m; i++)
    {
        la[i].push_back(t);
        capacitate[i][t] = 1;
    }
}

bool ConstruiesteDrumBF()
{
    int nod;
    vector<bool> viz(n + m + 2, false);
    viz[s] = true;

    tata.assign(n + m + 2, -1);

    queue<int> q;
    q.push(s);
    while (!q.empty())
    {
        int nod_curent = q.front();
        q.pop();
        for (auto &vecin : la[nod_curent])
        {
            // daca vecinul este vizitat sau capacitatea este folosită la maxim sărim peste
            if (viz[vecin] || capacitate[nod_curent][vecin] <= flux[nod_curent][vecin])
                continue;

            q.push(vecin);
            viz[vecin] = true;
            tata[vecin] = nod_curent;

            // dacă am ajuns la destinația finală
            if (vecin == t)
                return true;
        }
    }

    return false;
}

int main()
{
    Read();
    int flow = flux_initial, fmin;

    while (ConstruiesteDrumBF())
    {
        fmin = INT_MAX;
        // aflam capacitatea reziduală minimă
        for (int nod = t; nod != s; nod = tata[nod])
        {
            fmin = min(fmin, capacitate[tata[nod]][nod] - flux[tata[nod]][nod]);
        }

        // revizuim fluxul
        for (int nod = t; nod != s; nod = tata[nod])
        {
            // actualizam pe muchiile directe
            flux[tata[nod]][nod] += fmin;

            // actualizam pe muchiile inverse
            flux[nod][tata[nod]] -= fmin;
        }

        flow += fmin;
    }

    g << flow << '\n';

    for (size_t nod = 1; nod <= n; nod++)
    {
        for (auto &vecin : la[nod])
        {
            if (flux[nod][vecin] == 1)
                g << nod << ' ' << vecin - n << '\n';
        }
    }

    return 0;
}