Cod sursa(job #2962227)

Utilizator alex2209alexPavel Alexandru alex2209alex Data 8 ianuarie 2023 00:17:48
Problema Cuplaj maxim in graf bipartit Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.63 kb
// Complexitate O(N * M)
#include <fstream>
#include <vector>
#include <queue>

using namespace std;
ifstream f("cuplaj.in");
ofstream g("cuplaj.out");
struct str {
    int nod, destinatie, capacitate;
};
int n, m, destinatie, raspuns, nrMuchii = -1;
vector<int> muchiiId[20002], parinte, ap;
vector<str> muchii;
queue<int> q;

void citeste(), adaugaSursaSiDestinatie(), afisare();
int flux();

int main()
{
    citeste();
    adaugaSursaSiDestinatie();
    afisare();
    g.close();
    return 0;
}

void afisare() {
    g << flux() << '\n';
    for(auto it : muchii) {
        int nod = it.nod;
        int dest = it.destinatie;
        int c = it.capacitate;
        if(nod && destinatie - dest && !c && nod < dest) {
            g << nod << " " << dest - n << '\n';
        }
    }
}

bool bfs() {
    parinte.clear();
    parinte.resize(destinatie + 2);
    ap.clear();
    ap.resize(destinatie + 2);
    // Adaug sursa in coada
    q.push(0);
    ap[0] = 1;
    // Cat timp mai am elemente in coada
    while(!q.empty()){
        int nod = q.front();
        q.pop();
        if(nod == destinatie)
            continue;
        // Verific daca pot sa mai pun flow pe muchiile catre vecinii nodului curent
        for(auto it : muchiiId[nod]){
            // Daca vecinul nu e vizitat si se poate adauga flow pe muchia de la nod la el
            if(!ap[muchii[it].destinatie] && muchii[it].capacitate){
                // Parintele vecinului este nodul curent si vecinul e vizitat si adaugat in coada
                parinte[muchii[it].destinatie] = it;
                ap[muchii[it].destinatie] = 1;
                q.push(muchii[it].destinatie);
            }
        }
    }
    return ap[destinatie];
}

int flux()
{
    while(bfs()) {
        for(auto it : muchiiId[destinatie]){
            if(ap[muchii[it].destinatie] && muchii[it - 1].capacitate) {
                int nod = destinatie, flux = 1;
                parinte[destinatie] = it - 1;
                while(nod != 0) {
                    flux = min(flux, muchii[parinte[nod]].capacitate);
                    nod = muchii[parinte[nod]].nod;
                }
                nod = destinatie;
                while(nod != 0 && flux != 0) {
                    int muchieInversa = parinte[nod] + 1;
                    if(parinte[nod] % 2) {
                        muchieInversa = parinte[nod] - 1;
                    }
                    muchii[parinte[nod]].capacitate -= flux;
                    muchii[muchieInversa].capacitate += flux;
                    nod = muchii[parinte[nod]].nod;
                }
                raspuns += flux;
            }
        }
    }
    return raspuns;
}

void adaugaSursaSiDestinatie() {
    for(int i = 1; i <= n; ++i) {
        nrMuchii++;
        muchii.push_back({0, i, 1});
        muchiiId[0].push_back(nrMuchii);
        nrMuchii++;
        muchii.push_back({i, 0, 0});
        muchiiId[i].push_back(nrMuchii);
    }
    for(int i = 1; i <= m; ++i) {
        nrMuchii++;
        muchii.push_back({i + n, destinatie, 1});
        muchiiId[i + n].push_back(nrMuchii);
        nrMuchii++;
        muchii.push_back({destinatie, i + n, 0});
        muchiiId[destinatie].push_back(nrMuchii);
    }
}

void citeste()
{
    int e;
    f >> n >> m >> e;
    destinatie = n + m + 1;
    while(e--) {
        int x, y;
        f >> x >> y;
        nrMuchii++;
        muchii.push_back({x, y + n, 1});
        muchiiId[x].push_back(nrMuchii);
        nrMuchii++;
        muchii.push_back({y + n, x, 0});
        muchiiId[y + n].push_back(nrMuchii);
    }
    f.close();
}