Cod sursa(job #2962693)

Utilizator lucianul31Moisii Lucian lucianul31 Data 8 ianuarie 2023 23:02:45
Problema Cuplaj maxim in graf bipartit Scor 10
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.14 kb
#include <fstream>
#include <vector>
#include <queue>
#include <string.h>

using namespace std;

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


struct Edge
{
    int X, Y, Flow, Position;
};


const int NMAX = 1e4 + 5, MMAX = 3e5 + 5;
int Father[NMAX], N, M, E, Source, Destination, TotalFlow, nrEdges = -1;
bool Seen[NMAX];
vector < int > Graph[NMAX];
Edge Edges[MMAX];
queue < int > Q;

int BFS()
{
    int X, Flow = 0, Bottleneck;
    memset(Seen, 0, Destination + 1);
    Seen[Source] = 1;
    Q.push(Source);
    while(!Q.empty())
    {
        X = Q.front();
        Q.pop();
        for(int newX : Graph[X])
        {
            if(Edges[newX].Y == Destination)
                continue;
            if(!Seen[Edges[newX].Y] && Edges[newX].Flow > 0)
                Q.push(Edges[newX].Y), Seen[Edges[newX].Y] = 1, Father[Edges[newX].Y] = newX;
        }
    }
    for(int it : Graph[Destination])
    {
        if(!Seen[Edges[it].Y] || Edges[Edges[it].Position].Flow == 0)
            continue;
        Bottleneck = 2;
        Father[Destination] = Edges[it].Position;
        for(int x = Destination; x != Source; x = Edges[Father[x]].X)
            Bottleneck = min(Bottleneck, Edges[Father[x]].Flow);
        Flow += Bottleneck;
        for(int x = Destination; x != Source; x = Edges[Father[x]].X)
            Edges[Father[x]].Flow -= Bottleneck, Edges[Edges[Father[x]].Position].Flow += Bottleneck;
    }
    return Flow;
}

int main()
{
    int x, y;
    in >> N >> M >> E;
    Destination = N + M + 1;
    for(int i = 1; i <= E; i++)
    {
        in >> x >> y;
        Edges[++nrEdges].X = x;
        Edges[nrEdges].Y = N + y;
        Edges[nrEdges].Flow = 1;
        Edges[nrEdges].Position = nrEdges + 1;
        Graph[x].push_back(nrEdges);
        Edges[++nrEdges].X = y + N;
        Edges[nrEdges].Y = x;
        Edges[nrEdges].Flow = 0;
        Edges[nrEdges].Position = nrEdges - 1;
        Graph[y].push_back(nrEdges);
    }
    for(int i = 1; i <= N; i++)
    {
        Edges[++nrEdges].X = Source;
        Edges[nrEdges].Y = i;
        Edges[nrEdges].Flow = 1;
        Edges[nrEdges].Position = nrEdges + 1;
        Graph[Source].push_back(nrEdges);
        Edges[++nrEdges].X = i;
        Edges[nrEdges].Y = Source;
        Edges[nrEdges].Flow = 0;
        Edges[nrEdges].Position = nrEdges - 1;
        Graph[i].push_back(nrEdges);
    }
    for(int i = N + 1; i < Destination; i++)
    {
        Edges[++nrEdges].X = i;
        Edges[nrEdges].Y = Destination;
        Edges[nrEdges].Flow = 1;
        Edges[nrEdges].Position = nrEdges + 1;
        Graph[i].push_back(nrEdges);
        Edges[++nrEdges].X = Destination;
        Edges[nrEdges].Y = i;
        Edges[nrEdges].Flow = 0;
        Edges[nrEdges].Position = nrEdges - 1;
        Graph[Destination].push_back(nrEdges);
    }
    x = BFS();
    while (x)
    {
        TotalFlow += x;
        x = BFS();
    }
    out << TotalFlow << '\n';
    for(Edge &it : Edges)
        if(it.Flow == 0 && it.X != 0 && it.Y != Destination && it.X < it.Y)
            out << it.X << ' ' << it.Y - N << '\n';
    return 0;
}