Cod sursa(job #2962347)

Utilizator bbia17Baicoianu Bianca bbia17 Data 8 ianuarie 2023 13:03:22
Problema Cuplaj maxim in graf bipartit Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.64 kb
#include <iostream>
#include <fstream>
#include <vector>
#include <queue>
#include <climits>
using namespace std;

ifstream fin("cuplaj.in");
ofstream fout("cuplaj.out");

int N, M, E, nr, x, y, sursa, dest;

struct muchie
{
    int nod1, nod2, capacitate, poz;
};
vector<muchie> muchii;

//matrice indici--> indicii muchiilor incidente nodului
vector<vector<int>> mIndici;
vector<bool> viz;
vector<int> tata;

void adMuchie(int x, int y)
{
    int p = (int)muchii.size();
    muchie m;

    // adaugam indicii muchiei 
    mIndici[y].push_back(p + 1);

    // adaugam muchia de capacitate 1
    m.nod1 = x;
    m.nod2 = y;
    m.capacitate = 1;
    m.poz = p + 1;
    muchii.push_back(m);

    // repetam pentru inversa
    mIndici[x].push_back(p);

    // adaugam muchia de capacitate 0
    m.nod1 = y;
    m.nod2 = x;
    m.capacitate = 0;
    m.poz = p;
    muchii.push_back(m);
}

bool BFS()
{
    tata.clear();
    tata.resize(nr);
    viz.clear();
    viz.resize(nr, false);

    viz[sursa] = true;

    queue<int> q;
    q.push(sursa);

    while (!q.empty())
    {
        int nod = q.front();
        q.pop();

        if (nod != dest)
        {
            // iteram prin indicii muchiilor incidente
            for (int i : mIndici[nod])
            {
                muchie m = muchii[i];

                if (!viz[m.nod2] && m.capacitate != 0)  // conditie nod nevizitat&capacitate nedepasita
                {
                    tata[m.nod2] = i;   // actualizam tatal
                    
                    viz[m.nod2] = true;
                    q.push(m.nod2);
                }
            }
        }
    }

    return viz[dest]; // false --> flux maxim
}

int FordFulkerson()
{
    int maxFlux = 0;

    while (BFS())   // cat timp fluxul nu e maxim
    {
        // parcurgem drumul gasit
        for (int i : mIndici[dest])
        {
            muchie m = muchii[i];

            if (viz[m.nod2] && muchii[m.poz].capacitate != 0)   // cond nod vizitat si capacitate nedepasita
            {
                tata[dest] = m.poz;
                
                // determinam val min a muchiilor de pe drumul gasit
                int flux = INT_MAX;
                for (int nod = dest; nod != sursa; nod = muchii[tata[nod]].nod1)
                    flux = min(flux, muchii[tata[nod]].capacitate);

                // actualizam valorile de pe drum + inversele lor
                for (int nod = dest; nod != sursa; nod = muchii[tata[nod]].nod1)
                {
                    muchii[tata[nod]].capacitate -= flux;
                    muchii[muchii[tata[nod]].poz].capacitate += flux;
                }

                maxFlux += flux;
            }
        }
    }
    return maxFlux;
}

int main()
{
    fin >> N >> M >> E;
    nr = N + M + 2;   // nr total de noduri
    // se adauga nod sursa si nod des
    sursa = 0, dest = nr - 1;

    mIndici.resize(nr);

    for (int i = 0; i < E; i++)
    {
        fin >> x >> y;

        adMuchie(x, y + N); // y+N pentru a nu se suprapune pozitiile
    }

    // adaugam muchii de la nodul sursa la toate celelalte din prima multime
    for (int i = 1; i <= N; i++)
        adMuchie(sursa, i);

    // adaugam muchii de la nodul dest la cele din a doua multime
    for (int i = 1; i <= M; i++)
        adMuchie(i + N, dest);


    fout<<FordFulkerson()<<'\n';    // valoarea cuplajului maxim
    for (muchie m : muchii)
        if (m.nod1 < m.nod2 && m.nod1 != sursa && m.nod2 != dest && m.capacitate == 0)
            fout<<m.nod1<<' '<<m.nod2 - N<<'\n';    // muchiile din cuplaj
    return 0;
}