Cod sursa(job #2956322)

Utilizator AdelaCorbeanuAdela Corbeanu AdelaCorbeanu Data 19 decembrie 2022 03:43:16
Problema Cuplaj maxim in graf bipartit Scor 50
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.66 kb
/*
    Procedam analog problemei Flux maxim, cu diferenta ca toate capacitatile vor fi 1
    si vom adauga grafului doua noduri inainte de a rula flux pe el:
        -> un nod de start care are muchie cu toate nodurile din primul set
        -> un nod de final care are muchie cu toate nodurile din al doilea set
    Rulam algoritmul de determinare a fluxului maxim si rezultatul va fi cuplajul cautat.
    Pentru a obtine muchiile ce alcatuiesc cuplajul, vom afisa muchiile care leaga un nod
    din primul set cu un nod din al doilea set si au capacitate 0 (adica le-am utilizat).
    Pentru reprezentarea grafului, am indexat nodurile astfel:
        -> nod start = 0
        -> primul set: 1 .. n
        -> al doilea set: n + 1 .. n + m
        -> nod final = n + m + 1
 */

#include <bits/stdc++.h>

int flow_after_BFS (std::vector<std::vector<int>> &adj_list,
                    std::vector<std::vector<int>> &capacity,
                    std::vector<int> &previous) {

    int n = adj_list.size() - 1;
    std::vector<bool> sel(n + 1, false);
    std::queue<int> bf_queue;

    bf_queue.push(0);
    sel[0] = true;

    while (!bf_queue.empty()) {
        int current = bf_queue.front();
        bf_queue.pop();

        for (auto nbh : adj_list[current]) {
            if (!sel[nbh] && capacity[current][nbh] > 0 && nbh != n) {
                sel[nbh] = true;
                bf_queue.push(nbh);
                previous[nbh] = current;
            }
        }
    }

    int max_flow_possible = 0;

    for (auto nbh : adj_list[n]) {
        if (!sel[nbh]) continue;

        int current_path_flow = capacity[nbh][n];
        int current = nbh;
        while (current != 0) {
            current_path_flow = std::min(current_path_flow, capacity[previous[current]][current]);
            current = previous[current];
        }

        capacity[nbh][n] -= current_path_flow;
        capacity[n][nbh] += current_path_flow;
        current = nbh;
        while (current != 0) {
            capacity[previous[current]][current] -= current_path_flow;
            capacity[current][previous[current]] += current_path_flow;
            current = previous[current];
        }

        max_flow_possible += current_path_flow;
    }

    return max_flow_possible;
}

int get_max_flow (std::vector<std::vector<int>> &adj_list,
                  std::vector<std::vector<int>> &capacity) {
    int n = adj_list.size() - 1;
    std::vector<int> previous(n + 1, -1);

    int total_max_flow = 0;
    int path_flow = flow_after_BFS(adj_list, capacity, previous);
    while (path_flow) {
        total_max_flow += path_flow;
        path_flow = flow_after_BFS(adj_list, capacity, previous);
    }

    return total_max_flow;
}

int main()
{
    std::ifstream fin("cuplaj.in");
    std::ofstream fout("cuplaj.out");

    int n, m, e;
    fin >> n >> m >> e;

    std::vector<std::vector<int>> adj_list(n + m + 2);
    std::vector<std::vector<int>> capacity(n + m + 2, std::vector<int>(m + n + 2, 0));

    for (int i = 1; i <= e; ++i) {
        int node1, node2;
        fin >> node1 >> node2;

        adj_list[node1].push_back(node2 + n);
        adj_list[node2 + n].push_back(node1);
        capacity[node1][node2 + n] = 1;
    }

    for (int i = 1; i <= n; ++i) {
        adj_list[0].push_back(i);
        adj_list[i].push_back(0);
        capacity[0][i] = 1;
    }

    for (int i = n + 1; i <= n + m; ++i) {
        adj_list[i].push_back(m + n + 1);
        adj_list[m + n + 1].push_back(i);
        capacity[i][m + n + 1] = 1;
    }

    fout << get_max_flow(adj_list, capacity) << '\n';
    for (int i = 1; i <= n; ++i)
        for (auto j : adj_list[i])
            if (!capacity[i][j] && j) fout << i << " " << j - n << '\n';

    return 0;
}