Cod sursa(job #2958538)

Utilizator alex_bb8Banilean Alexandru-Ioan alex_bb8 Data 26 decembrie 2022 21:23:14
Problema Cuplaj maxim in graf bipartit Scor 70
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.21 kb
#include <bits/stdc++.h>

using namespace std;

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

const int NMAX = 20002;

struct edge{
    int node, flow, capacity;
};

int n, m, e;
vector<edge> G[NMAX];
vector<edge> adjacent;

void add_edge(int x, int y){

    G[x].push_back({y, 0, 1});
    G[y].push_back({x, 0, 0});

    if(y == n + m + 1)
        adjacent.push_back({x, 0, 1});
}

void read(){

    f >> n >> m >> e;

    for(int i = 1; i <= e; ++i){
        int x, y;

        f >> x >> y;

        add_edge(x , n + y);
    }

}

bool BFS(int s, int t, vector<pair<int, int>>& parent){

    fill(parent.begin(), parent.end(), make_pair(-1, -1));

    queue<int> Q;

    Q.push(s);

    parent[s].first = -2;

    while(!Q.empty()){

        int node = Q.front();

        Q.pop();

        for(int i = 0; i < (int) G[node].size(); ++i){

            auto& link = G[node][i];

            if(parent[link.node].first == -1 && link.capacity - link.flow > 0){
                parent[link.node].first = node;
                parent[link.node].second = i;

                if(link.node == t)
                    return true;

                Q.push(link.node);
            }
        }

    }

    return false;
}

void solve(){

    int max_flow = 0, s = 0, t = n + m + 1;

    vector<pair<int, int>> parent(n + m + 3, make_pair(-1, -1)); // node, index

    for(int i = 1; i <= n; ++i)
        add_edge(s, i);

    for(int i = 1; i <= m; ++i)
        add_edge(n + i, t);

    while(BFS(s, t, parent)){
        for(auto& x : adjacent){

            if(x.capacity == 0 || parent[x.node].first == -1)
                continue;

            int path_flow = INT_MAX;

            parent[t].first = x.node;

            for(int i = 0; i < (int) G[x.node].size(); ++i)
                if(G[x.node][i].node == t){
                    parent[t].second = i;
                    break;
                }

            // find the max flow through the path
            for(int node = t; node != s; node = parent[node].first){
                int aux = parent[node].first, index_node = parent[node].second;

                path_flow = min(path_flow, G[aux][index_node].capacity - G[aux][index_node].flow);
            }

            // update
            for(int node = t; node != s; node = parent[node].first){
                int aux = parent[node].first, index_aux, index_node = parent[node].second;

                for(index_aux = 0; index_aux < G[node].size(); ++index_aux)
                    if(G[node][index_aux].node == aux)
                        break;

                if(path_flow > 0){

                    G[aux][index_node].flow += path_flow;
                    G[node][index_aux].flow -= path_flow;
                }
            }

            max_flow += path_flow;
        }
    }

    g << max_flow << '\n';

    for(int node = 1; node <= n; ++node){
        for(auto& link : G[node])
            if(link.flow == 1)
                g << node << ' ' << link.node - n << '\n';
    }

}

int main(){

    ios_base::sync_with_stdio(false);
    cin.tie(NULL);

    read();

    solve();

	f.close();
	g.close();

    return 0;
}