Cod sursa(job #2967067)

Utilizator deboradeleanuDebora Deleanu deboradeleanu Data 18 ianuarie 2023 23:04:58
Problema Cuplaj maxim in graf bipartit Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 2.86 kb
#include <bits/stdc++.h>

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

int st, dr, edges, s, t;

vector<bool> vizdr;
vector<pair<int, int>> tata;
vector<pair<int, int>> noduridr;
vector<vector<pair<int, pair<int, int>>>> graf;

void addmuchie(int u, int v) {
    graf[u].push_back({v, {1, graf[v].size()}});
    graf[v].push_back({u, {0, graf[u].size() - 1}});
    if (v == t)
        noduridr.push_back(make_pair(u, graf[u].size() - 1));
}

void citire() {
    fin >> st >> dr >> edges;
    s = 0;
    t = st + dr + 1;
    vizdr.resize(dr + 1);
    tata.resize(t + 1);
    graf.resize(t + 1);
    for (int i = 1; i <= st; i++)
        addmuchie(s, i);
    for (int i = 1; i <= edges; i++) {
        int u, v;
        fin >> u >> v;
        addmuchie(u, st + v);
        vizdr[v] = true;
    }
}

bool bf() {
    vector<bool> visited(t + 1);
    queue<int> q;
    q.push(s);
    visited[s] = true;
    tata[s] = {-1, -1};
    while (!q.empty()) {
        int u = q.front();
        q.pop();
        if (u == t) continue;

        int i = 0;
        for (auto node: graf[u]) {
            int v, c;
            v = node.first;
            c = node.second.first;
            if (!visited[v] and c) {
                tata[v] = {u, i};
                visited[v] = true;
                q.push(v);
            }
            i++;
        }
    }
    return visited[t];
}

int fordf() {
    int maxflow = 0;
    while (bf()) {
        for (auto nod: noduridr) {
            int u, v, i, j, min_path = 1;
            tata[t] = nod;
            v = t;
            //parcurgem invers
            while (tata[v].first != -1) {
                u = tata[v].first;
                i = tata[v].second;
                min_path = min(min_path, graf[u][i].second.first);
                v = u;
            }
            // Update the capacities of the edges and the reverse edges along the path
            v = t;
            while (tata[v].first != -1) {
                u = tata[v].first;
                i = tata[v].second;
                j = graf[u][i].second.second;
                graf[u][i].second.first -= min_path;
                graf[v][j].second.first += min_path;
                v = u;
            }
            maxflow += min_path;
        }
    }
    return maxflow;
}

int main() {

    citire();

    // Add edges from each node on the right side that has an incoming edge to the sink
    for (int i = 1; i <= dr; i++) {
        if (vizdr[i])
            addmuchie(st + i, t);
    }

    fout << fordf() << endl;

    for (int u = 1; u <= st; u++)
        for (auto nod: graf[u]) {
            int v, c;
            v = nod.first;
            c = nod.second.first;
            if (v && c == 0 && v != t)
                fout << u << " " << v - st << '\n';
        }
    return 0;
}