Cod sursa(job #2961343)

Utilizator andriciucandreeaAndriciuc Andreea andriciucandreea Data 6 ianuarie 2023 11:29:19
Problema Cuplaj maxim in graf bipartit Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 4.08 kb
#include <iostream>
#include <fstream>
#include <algorithm>
#include <vector>
#include <queue>
#include <climits>

using namespace std;

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

vector<pair<int, pair<long long int, int>>> towards[25000]; //nod, capacitate, pozitie

// lista de noduri care ajung la destinatie
vector<pair<int, int>> reach_dest;
vector<int> visited;

bool checked[25000];
pair<int, int> parent[25000];
int n, m, e, start, dest, curr_node, x, y;

int bfs()
{
    queue<int> q;

    visited.assign(dest + 1, 0);
    q.push(start);
    parent[start] = { -1, -1 };

    while (!q.empty())
    {
        curr_node = q.front();
        q.pop();
        visited[curr_node] = 1;
        if (curr_node == dest)
            break;

        for (int i = 0; i < towards[curr_node].size(); i++)
        {
            // daca nodul nu a fost vizitat si exista un drum valid
            if (visited[towards[curr_node][i].first] == 0
                && towards[curr_node][i].second.first > 0)
            {

                // adaugam nodul in coada, il marcam ca vizitat si retinem tatal
                q.push(towards[curr_node][i].first);
                visited[towards[curr_node][i].first];
                parent[towards[curr_node][i].first] = { curr_node, i };
            }
        }
    }
    return visited[dest];   // am ajuns sau nu la destinatie
}

int main()
{
    fin >> n >> m >> e;
    start = 0;
    dest = n + m + 1;

    for (int i = 1; i <= n; i++)
    {
        towards[start].push_back({ i, {1, 0} });
        towards[i].push_back({ start, {0, 0} });
        towards[i][towards[i].size() - 1].second.second = towards[start].size() - 1;
        towards[start][towards[start].size() - 1].second.second = towards[i].size() - 1;
    }

    for (int i = 1; i <= e; i++)
    {
        fin >> x >> y;

        towards[x].push_back({ n + y, {1, 0} });
        towards[n + y].push_back({ x, {0, 0} });
        checked[y] = true;
        towards[y + n][towards[y + n].size() - 1].second.second = towards[x].size() - 1;
        towards[x][towards[x].size() - 1].second.second = towards[y + n].size() - 1;
    }

    for (int i = 1; i <= m; i++)
    {
        if (checked[i])
        {
            towards[dest].push_back({ n + i, {0, 0} });
            towards[n + i].push_back({ dest, {1, 0} });
            reach_dest.push_back({ n + i, towards[n + i].size() - 1 });
            towards[dest][towards[dest].size() - 1].second.second = towards[n + i].size() - 1;
            towards[n + i][towards[n + i].size() - 1].second.second = towards[dest].size() - 1;
        }
    }

    int flow = 0;
    int position = 0;
    pair<int, int> node;

    while (bfs())
    {
        // parcurgem nodurile din care se poate ajunge la destinatie
        for (auto item : reach_dest)
        {
            long long int mini = INT_MAX;
            parent[dest] = item;
            node = parent[dest];
            int aux_dest = dest;

            while (node.first != -1)
            {
                // calculam distanta
                mini = min(mini, towards[node.first][node.second].second.first);
                node = parent[node.first];
            }

            flow = flow + mini;

            node = parent[dest];
            // actualizam capacitatile
            while (node.first != -1)
            {
                position = towards[node.first][node.second].second.second;
                towards[node.first][node.second].second.first -= mini;
                towards[aux_dest][position].second.first += mini;
                aux_dest = node.first;
                node = parent[node.first];
            }
        }
    }

    fout << flow << endl;

    for (int i = 1; i <= n; i++)
    {
        for (int j = 0; j < towards[i].size(); j++)
        {
            if (towards[i][j].first && towards[i][j].second.first == 0)
            {
                fout << i << " " << towards[i][j].first - n << endl;
            }
        }
    }

    fout.close();

}

// spatiu: O(VE)
// timp: O(VE)