Cod sursa(job #2961465)

Utilizator urluconceptualCiocan Alexandra-Diana urluconceptual Data 6 ianuarie 2023 15:41:00
Problema Cuplaj maxim in graf bipartit Scor 50
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.49 kb
#include <fstream>
#include <vector>
#include <queue>
#define INT_MAX 2147483647;

using namespace std;

//1. a) cuplaj maxim in graf bipartit

int n, m, cardN, cardM, maxFlow, start, final;
vector<vector<int>> adj, rez;
vector<int> anc;
vector<bool> viz;

//parcurgerea bfs care gaseste lanturi de la start la final:
bool bfs() {
    queue<int> q;
    anc.clear();
    anc.resize(n + 2, -1);
    viz.clear();
    viz.resize(n + 2, false);

    q.push(start);
    viz[start] = true;

    while (!q.empty()) {
        int curr = q.front();
        q.pop();

        if (curr == final)
            continue;

        for (int i = 0; i < adj[curr].size(); i++) {
            if (!viz[adj[curr][i]] && rez[curr][adj[curr][i]] > 0) {
                anc[adj[curr][i]] = curr;
                q.push(adj[curr][i]);
                viz[adj[curr][i]] = true;
            }
        }
    }
    return viz[final];
}

//algoritmul edmonds-karp:
void edmondsKarp() {
    //cat timp mai exista lanturi care pot fi parcurse de la start la final, continuam sa le parcurgem adaugand flux:
    while (bfs()) {
        //pentru toate drumurile care au dus la final:
        for (int i = 0; i < adj[final].size(); i++)
        {
            if (!(viz[adj[final][i]] && rez[adj[final][i]][final] != 0))
                continue;

            //caut bottleneck-ul, reprezentand noul flux:
            int aux = adj[final][i], min = 1;

            while (aux != start) {
                if (rez[anc[aux]][aux] == 0) {
                    min = 0;
                    break;
                }
                aux = anc[aux];
            }

            //updatez matricea reziduala, adaugand noul flux:
            if (min == 1) {
                aux = adj[final][i];

                rez[aux][final] -= min;
                rez[final][aux] += min;

                while (aux != start) {
                    rez[anc[aux]][aux] -= min;
                    rez[aux][anc[aux]] += min;
                    aux = anc[aux];
                }

                maxFlow += min;
            }
        }
    }
}


//citirea datelor: informatiile despre cele 2 multimi sunt modelate sub forma unui graf orientat bipartit la care vom adauga doua noduri suplimentare, start(0) si final(n+1),
//iar fiecare arc va avea o capacitate de 1
void citire() {
    ifstream fin("cuplaj.in");
    int nod1, nod2;
    fin >> cardN >> cardM >> m;
    n = cardN + cardM;
    adj.resize(n + 2);
    rez.resize(n + 2, vector<int>(n + 2, 0));

    start = 0;
    final = n + 1;

    for (int nod = 1; nod <= cardN; nod++) {
        adj[start].push_back(nod);
        adj[nod].push_back(start);
        rez[start][nod] = 1;
    }

    for (int nod = cardN + 1; nod <= n; nod++) {
        adj[final].push_back(nod);
        adj[nod].push_back(final);
        rez[nod][final] = 1;
    }

    for (int i = 0; i < m; i++) {
        fin >> nod1 >> nod2;
        adj[nod1].push_back(nod2 + cardN);
        adj[nod2 + cardN].push_back(nod1);
        rez[nod1][nod2 + cardN] = 1;
    }
}

void afisare() {
    ofstream fout("cuplaj.out");

    fout << maxFlow << "\n";

    for (int i = 1; i <= cardN; i++)
        for (int j = 0; j < adj[i].size(); j++)
            if (rez[i][adj[i][j]] == 0 && adj[i][j] != start && adj[i][j] != final)
                fout << i << " " << adj[i][j]-cardN << "\n";

    fout.close();
}

int main()
{
    citire();
    edmondsKarp();
    afisare();
    return 0;
}