Cod sursa(job #2692338)

Utilizator stanciucalinStanciu Calin stanciucalin Data 2 ianuarie 2021 13:13:25
Problema Cuplaj maxim in graf bipartit Scor 50
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.78 kb
#include <iostream>
#include <fstream>
#include <unordered_map>
#include <queue>
using namespace std;

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

const int INF = 1000000000;

int l_card, r_card, m;
int n, n_init;

int max_flow;

unordered_map <int, int> * lv;

bool BFS(int t[]){
    /*
    cout << "lista de vecini curenta:\n";
    for(int i = 1; i <= n; i++){

        for(auto & next : lv[i]){

            cout << next.first << " " << next.second << ", ";
        }
        cout << '\n';
    }
    cout << "parcurgere curenta: ";
    */
    bool * viz = new bool [n + 1];

    t[1] = 0;

    for(int i = 1; i <= n; i++)
        viz[i] = 0;

    viz[1] = 1;

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

    while(!q.empty()){

        int current_node = q.front();
        q.pop();
        //cout << current_node << " ";
        for(auto & next : lv[current_node]){

            if(next.first == n){

                t[n] = current_node;

                return 0;
            }
            else if(!viz[next.first]){

                t[next.first] = current_node;
                viz[next.first] = 1;

                q.push(next.first);
            }
        }
    }

    return 1;
}

void Edmonds_Karp(){

    bool path_not_found;

    int * t = new int [n + 1];

    do{
        path_not_found = BFS(t);

        if(!path_not_found){

            /// prima iteratie prin vectorul de tati, pentru a determina muchia de capacitate minima

            int min_capacity = INF;
            //cout << " current_capacity pe tati: ";
            int node = n;
            while(t[node]){

                int current_capacity = lv[t[node]][node];
                //cout << current_capacity << " ";
                if(current_capacity < min_capacity)
                    min_capacity = current_capacity;

                node = t[node];
            }

            max_flow += min_capacity;
            //cout << " min_capacity: " << min_capacity;
            /// a doua iteratie pentru a modifica graful rezidual
            //cout << " | parcurgere tati: ";
            node = n;
            while(t[node]){
                //cout << t[node] << " ";
                int current_capacity = lv[t[node]][node];

                if(current_capacity == min_capacity){

                    lv[t[node]].erase(node);
                }
                else
                    lv[t[node]][node] -= min_capacity;

                if(lv[node].find(t[node]) != lv[node].end()){

                    lv[node][t[node]] += min_capacity;
                }
                else
                    lv[node][t[node]] = min_capacity;

                node = t[node];
            }

        }
        //cout << " max_flow: " << max_flow << '\n';
    }
    while(!path_not_found);
}

int main(){

    f >> l_card >> r_card >> m;

    n_init = l_card + r_card;
    n = n_init + 2;

    lv = new unordered_map <int, int> [n + 1];

    /// retin nodurile de la 2 la n_init + 1 iar la afisare pentru nodurile cu numar > l_card + 1 scad l_card (cele din R)
    /// nodul sursa al fluxului -> 1
    /// nodul destinatie al fluxului -> n_init + 2 = n

    int x, y;
    for(int i = 0; i < m; i++){

        f >> x >> y;

        lv[x + 1][y + l_card + 1] = 1;
    }

    for(int i = 2; i <= l_card + 1; i++)
        lv[1][i] = 1;

    for(int i = l_card + 2; i <= n_init + 1; i++)
        lv[i][n] = 1;

    Edmonds_Karp();

    g << max_flow << '\n';

    for(int i = l_card + 2; i <= n_init + 1; i++)
        for(auto & next_node : lv[i]){

            if(next_node.first >= 2 && next_node.first <= l_card + 1){

                g << next_node.first - 1 << " " << i - l_card - 1 << '\n';
            }
        }

    return 0;
}