Cod sursa(job #2960529)

Utilizator woodyinhoStoica Elias-Valeriu woodyinho Data 4 ianuarie 2023 16:36:10
Problema Cuplaj maxim in graf bipartit Scor 50
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.81 kb
#include <iostream>
#include <fstream>
#include <vector>
#include <queue>
#include <algorithm>
#include <string>

using namespace std;

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

vector<vector<int>> graf;
vector<int> vizitat;
vector<int> tata;
vector<vector<int>> capacitate;

int n, m, sursa, dest, l, r;

bool bfs(){
    tata.clear();
    tata.resize(n + 3);
    fill(vizitat.begin(), vizitat.end(), 0);
    queue<int> coada;
    coada.push(sursa);
    vizitat[sursa] = 1;

    while(!coada.empty()){
        int nod = coada.front();
        coada.pop();
        if(nod == dest)
            continue;
        for(auto &vecin:graf[nod]){
            if(!vizitat[vecin] && capacitate[nod][vecin] > 0){
                vizitat[vecin] = 1;
                tata[vecin] = nod;
                coada.push(vecin);
            }
        }
    }
    return vizitat[dest];
}

int fluxMaxim(){
    int maxFlux = 0;
    //facem bfs cat timp mai exista drumuri de la sursa la destinatie pe care sa le verificam pentru fluxul maxim
    while(bfs()){
        //daca am ajuns la destinatie, inseamna ca am gasit un nou drum si verificam fluxul maxim pe acest drum
        for(auto vecin: graf[dest]){
            if(vizitat[vecin] && capacitate[vecin][dest] > 0){
                int flux = 1e9;
                int nod = dest;
                //parcurgem drumul de la destinatie la sursa si aflam fluxul maxim pe acest drum
                while(nod != sursa){
                    flux = min(flux, capacitate[tata[nod]][nod]);
                    nod = tata[nod];
                }
                //actualizam fluxul maxim
                maxFlux += flux;
                //actualizam capacitatea muchiilor
                nod = dest;
                while(nod != sursa){
                    capacitate[tata[nod]][nod] -= flux;
                    capacitate[nod][tata[nod]] += flux;
                    nod = tata[nod];
                }
            }
        }
    }
    return maxFlux;
}

int main() {

    f>>l>>r>>m;
    n = l + r;
    sursa = 1;
    dest = n + 2;
    graf.resize(n + 3);
    vizitat.resize(n + 3);
    tata.resize(n + 3); //tata[i] = nodul din care am ajuns in nodul i
    capacitate.resize(n + 3, vector<int>(n+3)); //capacitatea maxima a muchiei (i,j)

    for(int i = 1; i <= m; i++){
        int x, y;
        f>>x>>y;
        graf[x + 1].push_back(y + l + 1);
        graf[y + l + 1].push_back(x + 1);
        capacitate[x + 1][y + l + 1] = 1;
    }
    //adaugam un nod sursa care va fi nodul 1 si un nod destinatie care va fi nodul n+2
    //facem muchii de la sursa la fiecare nod din stanga si de la fiecare nod din dreapta la destinatie
    //capacitatea maxima a acestor muchii va fi 1
    //reducem problema determinarii unui cuplaj maxim intr un graf bipartit la problema
    //determinarii unui flux maxim intr-o retea de transport asociata acelui graf bipartit si cu adaugarea
    //nodurilor sursa si destinatie

    for(int i = 2; i <= l + 1; i++){
        graf[sursa].push_back(i);
        graf[i].push_back(sursa);
        capacitate[sursa][i] = 1;
    }

    for(int i = l + 2; i <= n + 1; i++){
        graf[i].push_back(dest);
        graf[dest].push_back(i);
        capacitate[i][dest] = 1;
    }

    //afisare matrice de capacitate
//    for(int i = 1; i <= dest; i++){
//        for(int j = 1; j <= dest; j++){
//            cout<<capacitate[i][j]<<" ";
//        }
//        cout<<endl;
//    }

    g<<fluxMaxim()<<"\n";

    //nodurile cuplate vor reprezenta arcele care fac parte din cuplajul maxim si au capacitatea 0 in matricea de capacitate
    //si care nu sunt adiacente cu nodul sursa sau destinatie
    for(int i = 2; i <= l + 1; i++){
        for(auto vecin: graf[i]){
            if(capacitate[i][vecin] == 0 && vecin != dest && vecin != sursa){
                g<<i - 1<<" "<<vecin - l - 1<<"\n";
            }
        }
    }
    return 0;
}