Cod sursa(job #2960481)

Utilizator moise_alexandruMoise Alexandru moise_alexandru Data 4 ianuarie 2023 14:49:39
Problema Cuplaj maxim in graf bipartit Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.79 kb
#include <algorithm>
#include <iostream>
#include <fstream>
#include <vector>
#include <queue>
using namespace std;
ifstream in("cuplaj.in");
ofstream out("cuplaj.out");
const int maxn = 20005;

struct muchie {
    int vec;
    int flux;
    int cap;
};

vector <muchie> v[maxn];
int dist[maxn];
int tata[maxn];
int sursa, destinatie;

queue <int> q;
int n;

int cautbin(int x, int y)
{
    int st = 0;
    int dr = v[x].size() - 1;
    while(st <= dr)
    {
        int mij = (st + dr) / 2;
        if(v[x][mij].vec < y)
            st = mij + 1;
        else if(v[x][mij].vec > y)
            dr = mij - 1;
        else
            return mij;
    }
    return -1;
}

int gasiremuchie(int x, int y) /// gaseste indicele muchiei (x, y), returneaza -1 daca nu exista
{
    if(v[x].size() >= 100)
        return cautbin(x, y);
    for(int i = 0; i < v[x].size(); i++)
        if(v[x][i].vec == y)
            return i;
    return -1;
}

bool bfs()
{
    for(int i = 1; i <= n; i++)
        dist[i] = (1 << 30);
    dist[sursa] = 0;
    q.push(sursa);
    while(!q.empty())
    {
        int nod = q.front();
        q.pop();
        if(nod == destinatie)
            continue;
        for(auto m : v[nod])
        {
            if(dist[m.vec] > dist[nod] + 1 && m.flux < m.cap)
            {
                dist[m.vec] = dist[nod] + 1;
                tata[m.vec] = nod;
                q.push(m.vec);
            }
        }
    }
    if(dist[destinatie] == (1 << 30))
        return 0;
    return 1;
}

vector <pair <int, int> > input;

inline bool cmp(muchie a, muchie b)
{
    return a.vec < b.vec;
}

int main()
{
    int m, e;
    in >> n >> m >> e;
    int ninit = n;
    sursa = n + m + 1;
    destinatie = n + m + 2;
    for(int i = 1; i <= e; i++)
    {
        int x, y;
        in >> x >> y;
        v[x].push_back({y + n, 0, 1});
        v[y + n].push_back({x, 0, 0});
        input.push_back(make_pair(x, y));
    }
    for(int i = 1; i <= n; i++)
    {
        v[sursa].push_back({i, 0, 1});
        v[i].push_back({sursa, 0, 0});
    }
    for(int i = 1; i <= m; i++)
    {
        v[i + n].push_back({destinatie, 0, 1});
        v[destinatie].push_back({i + n, 0, 0});
    }
    n = n + m + 2;
    for(int i = 1; i <= n; i++)
        sort(v[i].begin(), v[i].end(), cmp);
    while(bfs())
    {
        for(auto it : v[destinatie])
        {
            int col = gasiremuchie(it.vec, destinatie);
            if(dist[it.vec] == (1 << 30) || v[it.vec][col].flux == v[it.vec][col].cap)
                continue;
            tata[destinatie] = it.vec;
            int act = destinatie;
            vector <int> drum;
            while(tata[act] != 0)
            {
                drum.push_back(act);
                act = tata[act];
            }
            drum.push_back(act);
            reverse(drum.begin(), drum.end());
            int topush = (1 << 30);
            for(int i = 0; i < drum.size() - 1; i++)
            {
                int aux = gasiremuchie(drum[i], drum[i + 1]);
                topush = min(topush, v[drum[i]][aux].cap - v[drum[i]][aux].flux);
            }
            for(int i = 0; i < drum.size() - 1; i++)
            {
                v[drum[i]][gasiremuchie(drum[i], drum[i + 1])].flux += topush;
                v[drum[i + 1]][gasiremuchie(drum[i + 1], drum[i])].flux -= topush;
            }
        }
    }
    int sol = 0;
    for(auto it : v[sursa])
        sol = sol + it.flux;
    out << sol << "\n";
    //for(auto it : v[1])
        //cout << it.vec << " " << it.flux << " " << it.cap << "\n";
    for(auto it : input)
        if(v[it.first][gasiremuchie(it.first, it.second + ninit)].flux == 1)
            out << it.first << " " << it.second << "\n";
    return 0;
}