Cod sursa(job #2959971)

Utilizator radubuzas08Buzas Radu radubuzas08 Data 3 ianuarie 2023 12:39:35
Problema Cuplaj maxim in graf bipartit Scor 50
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.76 kb
#include <fstream>
#include <vector>
#include <queue>
using namespace std;

ifstream in("cuplaj.in");
ofstream out("cuplaj.out");
int l, r, m;
class Flow
{
    int source, sink;
    int n;
    int maxFlow;
    std::vector<bool> visited;
    std::vector<std::vector<int> > graph;
    std::vector<std::vector<int> > capacity;
    std::vector<std::vector<int> > flow;
    std::vector<int> father;

    void dfs(int x) {
        visited[x] = true;
        for (int node : graph[x]) {
            if (!visited[node] && flow[x][node] < capacity[x][node]) {
                dfs(node);
            }
        }
    }

    bool bfs()
    {
        visited.assign(n+1, false);
        std::queue<int> q;
        q.push(source);
        visited[source] = true;

        while(!q.empty())
        {
            int node = q.front();
            q.pop();

            for(int neighbour : graph[node])
            {
                if(capacity[node][neighbour] == flow[node][neighbour] || visited[neighbour])
                    continue;
                visited[neighbour] = true;
                q.push(neighbour);
                father[neighbour] = node;
                if(neighbour == sink)
                    return true;
            }
        }
        return false;
    }


public:
    Flow(int n, int source, int sink)
    {
        this->source = source;
        this->sink = sink;
        this->n = n;
        this->maxFlow = 0;
        capacity.resize(n + 1, std::vector<int>(n + 1));
        flow.resize(n + 1, std::vector<int>(n + 1));
        graph.resize(n + 1);
        visited.resize(n + 1);
        father.resize(n + 1);
    }

    void addEdge(int x, int y, int cost = 1)
    {
        if(capacity[x][y] == 0)
        {
            graph[x].push_back(y);
            graph[y].push_back(x);
        }
        capacity[x][y] += cost;
    }

    int getMaxFlow()
    {
        int maxFlow = 0;
        do{
            if( !bfs() )
                break;
            for (auto nod : graph[n]) {
                if(capacity[nod][n] == flow[nod][n] || visited[nod] == 0)
                    continue;

                father[n] = nod;
                int flowMin = 0x7fffffff;
                for (int i = sink; i; i = father[i])
                    flowMin = std::min(flowMin, capacity[father[i]][i] - flow[father[i]][i]);
                if (flowMin == 0)
                    continue;

                maxFlow += flowMin;
                for (int i = sink; i; i = father[i]) {
                    flow[father[i]][i] += flowMin;
                    flow[i][father[i]] -= flowMin;
                }
            }
        } while (true);
        return maxFlow;
    }

    int getFlow() const{
        return maxFlow;
    }

    std::vector<std::pair<int, int>> getMinCut()
    {
        visited.assign(n+1, false);
        for (int i = 1; i <= n/2; ++i) {
            flow[source][i] = 0;
        }

        dfs(source);
        std::vector<std::pair<int, int>> minCut;
        for (int i = source; i <= sink; ++i) {
            for (int j : graph[i]) {
                if (visited[i] && !visited[j] && capacity[i][j] > 0)
                    minCut.emplace_back(i, j);
            }
        }
        return minCut;
    }

    void printGraph() {
        for (int i = 1; i <= l; ++i)
            for (int j = l + 1; j <= n; ++j)
                if (flow[i][j] > 0)
                    out << i << ' ' << j - l << '\n';
    }

};

int main() {
    in >> l >> r >> m;
    Flow f(l + r + 1, 0, l + r + 1);

    for (int i = 1; i <= l; ++i)
        f.addEdge(0, i);
    for (int i = l + 1; i <= l + r; ++i)
        f.addEdge(i, l + r + 1);

    int x, y;
    while (m--) {
        in >> x >> y;
        f.addEdge(x, l + y);
    }
    in.close();

    int sol = f.getMaxFlow();

    out << sol << '\n';
    f.printGraph();
    out.close();
    return 0;
}