Cod sursa(job #2874715)

Utilizator beingsebiPopa Sebastian beingsebi Data 20 martie 2022 00:10:56
Problema Cuplaj maxim in graf bipartit Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 4.35 kb
#include <bits/stdc++.h>
using namespace std;
class InParser
{
private:
    FILE *fin;
    char *buff;
    int sp;

    char read_ch()
    {
        ++sp;
        if (sp == 4096)
        {
            sp = 0;
            fread(buff, 1, 4096, fin);
        }
        return buff[sp];
    }

public:
    InParser(const char *nume)
    {
        fin = fopen(nume, "r");
        buff = new char[4096]();
        sp = 4095;
    }

    InParser &operator>>(int &n)
    {
        char c;
        while (!isdigit(c = read_ch()) && c != '-')
            ;
        int sgn = 1;
        if (c == '-')
        {
            n = 0;
            sgn = -1;
        }
        else
        {
            n = c - '0';
        }
        while (isdigit(c = read_ch()))
        {
            n = 10 * n + c - '0';
        }
        n *= sgn;
        return *this;
    }
};
InParser f("cuplaj.in");
ofstream g("cuplaj.out");
// #define f cin
// #define g cout
const int nmax = 20009;
struct Edge
{
    int to, capacity, flow;
    int index;
    int remaining_capacity() const
    {
        return capacity - flow;
    }
};

int source, sink;
int n, boys, girls, visited[nmax], vtoken = 1, level[nmax], nexti[nmax];
vector<Edge> v[nmax];
void get_graph();
bool bfs();
int dfs(int, int);
int get_max_flow();
int32_t main()
{
    get_graph();
    g << get_max_flow() << '\n';
    for (int i = 1; i <= boys; i++)
        for (int j = 0; j < (int)v[i].size(); j++)
            if (v[i][j].capacity && v[i][j].flow)
                g << i << " " << v[i][j].to - boys << '\n';
    return 0;
}
void get_graph()
{
    int k;
    f >> boys >> girls >> k;
    n = boys + girls + 2;
    source = n + 1;
    sink = n + 2;
    for (int i = 1; i <= boys; i++)
    {
        static Edge to, xto;
        to.capacity = 1;
        to.flow = 0;
        to.to = i;

        xto.capacity = 0;
        xto.flow = 0;
        xto.to = source;

        to.index = v[i].size();
        xto.index = v[source].size();

        v[source].push_back(to);
        v[i].push_back(xto);
    }
    for (int i = 1; i <= girls; i++)
    {
        static Edge to, xto;
        to.capacity = 1;
        to.flow = 0;
        to.to = sink;

        xto.capacity = 0;
        xto.flow = 0;
        xto.to = i + boys;

        to.index = v[sink].size();
        xto.index = v[i + boys].size();

        v[i + boys].push_back(to);
        v[sink].push_back(xto);
    }
    for (int x, y; k; k--)
    {
        f >> x >> y;
        static Edge to, xto;
        to.capacity = 1;
        to.flow = 0;
        to.to = y + boys;

        xto.capacity = 0;
        xto.flow = 0;
        xto.to = x;

        to.index = v[y + boys].size();
        xto.index = v[x].size();

        v[x].push_back(to);
        v[y + boys].push_back(xto);
    }
}
int get_max_flow()
{
    int max_flow = 0;
    while (bfs())
    {
        vtoken++;
        memset(nexti, 0, sizeof nexti);
        for (int minim = dfs(source, INT_MAX); minim; minim = dfs(source, INT_MAX))
            vtoken++, max_flow += minim;
        vtoken++;
    }
    return max_flow;
}
bool bfs()
{
    static queue<int> q;
    visited[source] = vtoken;
    level[source] = 1;
    q.push(source);
    while (!q.empty())
    {
        static int ac;
        ac = q.front();
        q.pop();
        for (const Edge &i : v[ac])
            if (visited[i.to] != vtoken && i.remaining_capacity() > 0)
            {
                visited[i.to] = vtoken;
                level[i.to] = level[ac] + 1;
                q.push(i.to);
            }
    }
    return (visited[sink] == vtoken);
}
int dfs(int x, int minim)
{
    visited[x] = vtoken;
    if (x == sink)
        return minim;
    for (int cap, ne, ax, to, ind; nexti[x] < (int)v[x].size(); nexti[x]++)
    {
        cap = v[x][nexti[x]].remaining_capacity();
        ne = v[x][nexti[x]].to;
        if (cap > 0 && visited[ne] != vtoken && level[x] <= level[ne])
        {
            ax = dfs(ne, min(cap, minim));
            if (ax > 0)
            {
                to = v[x][nexti[x]].to;
                ind = v[x][nexti[x]].index;
                v[x][nexti[x]].flow += ax;
                v[to][ind].flow -= ax;
                nexti[x]++;
                return ax;
            }
        }
    }
    return 0;
}