Cod sursa(job #2962750)

Utilizator AlexPascu007Pascu Ionut Alexandru AlexPascu007 Data 9 ianuarie 2023 00:17:37
Problema Cuplaj maxim in graf bipartit Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.03 kb
#include <fstream>
#include <vector>
#include <queue>
#include <bitset>
using namespace std;

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

struct Edge {
    int x, y, cap, poz;
};

int n, m, e, s, d, x, y;
vector <Edge> edges;
vector <vector<int>> graph;
vector <int> t;
bitset<20010> visited;


bool bfs() {
    visited.reset();
    queue <int> q;
    q.push(s);
    visited[s] = true;
    int node;
    while(!q.empty()) {
        node = q.front();
        q.pop();
        if(node == d)
            continue;
        for(auto it : graph[node]) {
            Edge edge = edges[it];
            if(!visited[edge.y] && edge.cap) {
                t[edge.y] = it;
                visited[edge.y] = true;
                q.push(edge.y);
            }
        }
    }
    return visited[d];
}
// algoritmul lui Edmonds-Karp pentru flux maxim
int getMaxFlow() {
    int answer = 0;
    while(bfs()) {
        for(auto it : graph[d]) {
            if(!visited[edges[it].y])
                continue;
            Edge edge = edges[it];
            t[d] = edge.poz;
            int minFlow = 2e9;
            for (int node = d; node != s; node = edges[t[node]].x) {
                if (edges[t[node]].cap < minFlow)
                    minFlow = edges[t[node]].cap;
            }
            if(minFlow == 0)
                continue;
            answer += minFlow;
            for (int node = d; node != s; node = edges[t[node]].x) {
                edges[t[node]].cap -= minFlow;
                edges[edges[t[node]].poz].cap += minFlow;
            }
        }
    }
    return answer; // fluxul maxim = cuplajul maxim
}


int main() {
    fin >> n >> m >> e;
    d = n + m + 1;
    graph = vector <vector<int>> (n + m + 2);
    t = vector <int> (n + m + 2);
    // adaugam muchiile de la nodurile din stanga la cele din dreapta
    for(int i = 1; i <= e; i ++) {
        fin >> x >> y;
        int dim = edges.size();
        graph[x].push_back(dim);
        graph[y + n].push_back(dim + 1);
        edges.push_back({x, y + n, 1, dim + 1});
        edges.push_back({y + n, x, 0, dim});
    }
    // adaugam muchiile de la sursa la nodurile din stanga
    for(int i = 1; i <= n; i ++) {
        int dim = edges.size();
        graph[s].push_back(dim);
        graph[i].push_back(dim + 1);
        edges.push_back({s, i, 1, dim + 1});
        edges.push_back({i, s, 0, dim});
    }
    // adaugam muchiile de la nodurile din dreapta la destinatie
    for(int i = n + 1; i <= n + m; i ++) {
        int edges_cnt = edges.size();
        graph[i].push_back(edges_cnt);
        graph[d].push_back(edges_cnt + 1);
        edges.push_back({i, d, 1, edges_cnt + 1});
        edges.push_back({d, i, 0, edges_cnt});
    }
    fout << getMaxFlow() << '\n';
    // afisam muchiile care fac parte din cuplaj = muchiile saturate
    for(auto edge : edges)
        if(edge.x < edge.y && edge.x != s && edge.y != d && edge.cap == 0)
            fout << edge.x << " " << edge.y - n << '\n';
    return 0;
}