Cod sursa(job #2966907)

Utilizator mbrianaMerealbe Cris-Briana mbriana Data 18 ianuarie 2023 17:48:45
Problema Cuplaj maxim in graf bipartit Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.89 kb
#include <iostream>
#include <fstream>
#include <vector>
#include <queue>
#include <algorithm>
#include <string>
using namespace std;

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

int n, m, e, source, sink,s;
vector<int> visited;
vector<int> parent;
vector<vector<int>> edges_pos;
struct edge
{
    int x, y, capacity, pos;
};
vector<edge> edges;

//alg normal de bfs folosit la Edmonds Karp
int bfs(){
    parent.clear();
    parent.resize(s);
    fill(visited.begin(), visited.end(), 0);
    queue<int> q;
    q.push(source);
    visited[source] = 1;

    while(!q.empty()){
        int nod = q.front();
        q.pop();
        if(nod == sink)
            continue;
        for(int i : edges_pos[nod]){
            edge m_curent = edges[i];
            if(!visited[m_curent.y] and m_curent.capacity != 0)
            {
                visited[m_curent.y] = 1;
                parent[m_curent.y] = i;
                q.push(m_curent.y);
            }
        }
    }
    return visited[sink];
}
//alg lui Edmonds Karp
int flux_Maxim(){
    int max_flow = 0;

    while(bfs()){
        for(auto i:edges_pos[sink]){
            if(visited[edges[i].y] and edges[edges[i].pos].capacity != 0)
            {
                int min_flow = 1e9;
                edge m_curent = edges[i];
                parent[sink] = m_curent.pos;
                int nod = sink;
                while(nod != source){
                    min_flow = min(min_flow, edges[parent[nod]].capacity);
                    nod = edges[parent[nod]].x;
                }
                nod = sink;
                while(nod != source){
                    edges[parent[nod]].capacity -= min_flow;
                    edges[edges[parent[nod]].pos].capacity += min_flow;
                    nod = edges[parent[nod]].x;
                }

                max_flow += min_flow;
            }
        }
    }

    return max_flow;
}

int main() {

    f>>n>>m>>e;
    //la graful nostru vom adauga doua noduri noi: source si sink
    //(exact cum aveam la problema de max flow)

    s = n + m + 2;//nr nou de noduri va creste cu 2
    //source va fi primul nod
    source = 0;
    //sink va fi ultimul nod
    sink = s - 1;
    visited.resize(s);
    parent.resize(s);
    edges_pos.resize(s);

    //Modificarile aduse alg lui Edmonds Karp:
    //legam nodul sursa de toate noduri din multimea L
    //legam toate nodurile din multimea L cu nodurile din multimea R
    //legam toate nodurile din multimea R cu nodul final
    //de asemenea, alegem capacitatea fiecarei muchii ca fiind 1, pentru a face matching 1 la 1
    for(int i = 1; i <= e; i++){
        int x, y;
        f>>x>>y;
        edges.push_back({x, y + n, 1, 2 * i - 1});
        edges.push_back({y + n, x, 0, 2 * i - 2});

        edges_pos[y + n].push_back(2 * i - 1);
        edges_pos[x].push_back(2 * i - 2);
    }

    int dimensiune_muchii = int (edges.size());

    for(int i = 1; i <= n; i++){

        dimensiune_muchii += 2;
        edges.push_back({source, i, 1, dimensiune_muchii - 1});
        edges.push_back({i, source, 0, dimensiune_muchii - 2});

        edges_pos[i].push_back(dimensiune_muchii - 1);
        edges_pos[source].push_back(dimensiune_muchii - 2);
    }

    for(int i = n + 1; i < s - 1; i++){

        dimensiune_muchii += 2;
        edges.push_back({i, sink, 1, dimensiune_muchii - 1});
        edges.push_back({sink, i, 0, dimensiune_muchii - 2});

        edges_pos[sink].push_back(dimensiune_muchii - 1);
        edges_pos[i].push_back(dimensiune_muchii - 2);

    }

    //apelam functia care ne va da fluxul maxim
    g<<flux_Maxim()<<"\n";
    for(auto & i : edges){
        //afisam muchiile pe care am facut matching
        if(i.capacity == 0 and i.x != source and i.y != sink and i.x < i.y){
            g<<i.x<<" "<<i.y - n<<"\n";
        }
    }

    return 0;
}