Cod sursa(job #2709033)

Utilizator Marius7122FMI Ciltea Marian Marius7122 Data 19 februarie 2021 17:36:20
Problema Cuplaj maxim in graf bipartit Scor 50
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.11 kb
#include <iostream>
#include <fstream>

#include <vector>
#include <queue>

class MaxFlowSolver
{
    void bfs(int startNode)
    {
        vis.assign(n + 1, false);
        std::queue<int> q;

        q.push(startNode);
        vis[startNode] = true;
        t[startNode] = 0;
        while(!q.empty())
        {
            int node = q.front();
            q.pop();

            if(node == n)
                continue;

            for(int y : g[node])
                if(cap[node][y] != flow[node][y])
                {
                    if(!vis[y])
                    {
                        vis[y] = true;
                        t[y] = node;
                        q.push(y);
                    }
                }
        }
    }

public:
    int n, fmax;
    std::vector<int> t;
    std::vector<std::vector<int>> cap, flow, g;
    std::vector<bool> vis;

    MaxFlowSolver(int _n)
    {
        n = _n;
        fmax = 0;

        cap.resize(n + 1, std::vector<int>(n + 1));
        flow.resize(n + 1, std::vector<int>(n + 1));
        g.resize(n + 1);
        t.resize(n + 1);
    }

    void addEdge(int x, int y, int c)
    {
        g[x].push_back(y);
        g[y].push_back(x);
        cap[x][y] = c;
    }

    int solve()
    {
        fmax = 0;
        do
        {
            bfs(1);

            if(vis[n] == false)
                break;
            
            for(int y : g[n])
            {
                if(vis[y] == false || cap[y][n] == flow[y][n])
                    continue;

                t[n] = y;

                int fmin = 1 << 30;
                for(int node = n; node != 1; node = t[node])
                    fmin = std::min(fmin, cap[t[node]][node] - flow[t[node]][node]);
                
                if(fmin == 0)
                    continue;

                fmax += fmin;
                for(int node = n; node != 1; node = t[node])
                {
                    flow[t[node]][node] += fmin;
                    flow[node][t[node]] -= fmin;
                }
            }
            
        } while(vis[n]);

        return fmax;
    }

    bool isEdgeFullAndNotEmpty(int x, int y)
    {
        return cap[x][y] > 0 && cap[x][y] == flow[x][y];
    }
    
};



using namespace std;

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

int n, m, e;

int main()
{
    fin >> n >> m >> e;

    MaxFlowSolver maxFlowSolver(n + m + 2);
    for(int i = 0; i < e; i++)
    {
        int x, y;
        fin >> x >> y;
        maxFlowSolver.addEdge(x + 1, y + n + 1, 1);
    }

    for(int i = 2; i <= n+1; i++)
        maxFlowSolver.addEdge(1, i, 1);
    for(int i = 1; i <= m; i++)
        maxFlowSolver.addEdge(n + i + 1, n + m + 2, 1);

    fout << maxFlowSolver.solve() << '\n';

    for(int i = 2; i <= n + 1; i++)
    {
        for(int j = n + 2; j <= n + m + 1; j++)
            if(maxFlowSolver.isEdgeFullAndNotEmpty(i, j))
                fout << i - 1 << ' ' << j - n - 1 << '\n';
    }

    fin.close();
    fout.close();
    return 0;
}

/*



*/