Cod sursa(job #2963798)

Utilizator stefan431245Oprea Mihai-Stefan stefan431245 Data 12 ianuarie 2023 00:35:31
Problema Cuplaj maxim in graf bipartit Scor 50
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.54 kb
#include <fstream>
#include <vector>
#include <queue>
#include <iostream>
using namespace std;

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

//O(N*M^2)
//n - numarul de noduri
//m - numarul de muchii

int n, m, x, a, b, flow, flux_max;
queue<int> q;
vector<vector<int>> graf;
vector<vector<int>> graf2;
vector<vector<int>> adj;
bool viz[10001];
int parent[10001];

int bfs(){
    while(!q.empty())
        q.pop();

    for(int i = 0; i <= n + m + 1; i++){
        parent[i] = 0;
        viz[i] = false;
    }

    //in coada este retinut nodul si capacitatea
    q.push(0);
    viz[0] = true;

    while(!q.empty()){

        int nod = q.front();
        q.pop();

        if(nod == n + m + 1){
            return true;
        }
        //cautam care sunt vecinii nodului curent si vedem daca a fost vizitat
        //daca nu vedem care este fluxul minim pana la acel nod si il retinem
        //daca am ajuns la destinatie returnam fluxul
        for(auto i : adj[nod]){
            if(!viz[i] && graf[nod][i] > 0){
                parent[i] = nod;
                viz[i] = true;
                q.push(i);
            }
        }

    }
    return 0;
}

int flux_maxim(){
    //daca am gasit un path atunci adunam fluxul la total si trecem prin path folosind vectorul de tati ca sa reconstruim graful
    flux_max = 0;

    while(bfs()){
        for(auto i : adj[n + m + 1]){
            if(parent[i]){
                parent[n + m + 1] = i;
                int flux = 1000001, nod_curent = n + m + 1;
                while(nod_curent != 0){
                    flux = min(flux, graf[parent[nod_curent]][nod_curent]);
                    nod_curent = parent[nod_curent];
                }

                nod_curent = n + m + 1;

                while(nod_curent != 0){
                    int prev = parent[nod_curent];
                    graf[nod_curent][prev] += flux;
                    graf[prev][nod_curent] -= flux;
                    nod_curent = prev;
                }

                flux_max += flux;
            }
        }
    }
    return flux_max;
}


void dfs(int nod){
    viz[nod] = true;

    for(int i = 1; i <= n + m; i++){
        if(graf[nod][i] && !viz[i]){
            dfs(i);
        }
    }
}

int main(){
    fin >> n >> m >> x;
    graf = vector<vector<int>>(n + m + 2, vector <int>(n + m + 2, 0));
    adj = vector<vector<int>>(n + m + 2);
    graf2 = vector<vector<int>>(n + m + 2, vector <int>(n + m + 2, 0));
    for(int i =  0; i < x; i ++){
        fin >> a >> b;
        graf[a][b + n] = 1;
        graf2[a][b + n] = 1;
        adj[a].push_back(b + n);
        adj[b + n].push_back(a);
    }
    //legam un nod de start de toate nodurile din coloana stanga

    for(int i = 1; i <= n; i++){
        graf[0][i] = 1;
        graf2[0][i] = 1;
        adj[0].push_back(i);
        adj[i].push_back(0);
    }

    //legam un nod de final de toate nodurile din coloana dreapta

    for(int i = 1; i <= m; i++){
        graf[i + n][n + m + 1] = 1;
        graf2[i + n][n + m + 1] = 1;
        adj[i + n].push_back(n + m + 1);
        adj[n + m + 1].push_back(i + n);
    }

    fout << flux_maxim() << endl;

    for(int i = 0; i <= n + m + 1; i++){
        viz[i] = false;
    }

    dfs(0);

    //comparam graf-ul vechi cu cel rezultat dupa flux_max

    for(int i = 1; i <= n; i++)
        for(int j = n + 1; j <= n + m; j++)
            if(!graf[i][j] && graf2[i][j])
                fout << i << " " << j - n << endl;
}