Cod sursa(job #3266221)

Utilizator stefan0211Tacu Darius Stefan stefan0211 Data 6 ianuarie 2025 17:09:39
Problema Cuplaj maxim in graf bipartit Scor 20
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.58 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;
    }

    // for (size_t nod = 1; nod <= la.size() - 1; nod++)
    // {
    //     for (size_t vecin = 0; vecin < la[nod].size(); vecin++)
    //     {
    //         g << nod << ' ' << la[nod][vecin] << ' ' << flux[nod][la[nod][vecin]] << '\n';
    //     }
    // }

    g << flow << '\n';

    // int nod;
    // vector<bool> viz(n + 1, false);
    // viz[s] = true;

    // 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])
    //             continue;
    //         else if (capacitate[nod_curent][vecin] == flux[nod_curent][vecin])
    //         {
    //             g << nod_curent << ' ' << vecin << '\n';
    //             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;

    return 0;
}