Pagini recente » Cod sursa (job #2845044) | Cod sursa (job #2329897) | Cod sursa (job #1837346) | Cod sursa (job #1890524) | Cod sursa (job #3190280)
#include <iostream>
#include <fstream>
#include <vector>
#include <queue>
#include <climits>
using namespace std;
ifstream in("harta.in");
ofstream out("harta.out");
bool BFS(int NodSursa, int nodDestinatie, vector <int>& tati, vector<vector<int>>& vecini, int N, vector<vector<int>> flux, vector<vector<int>> capacitate) {
queue <int> coada;
coada.push(NodSursa);
tati[NodSursa] = 0;
int drum = false;
while (!coada.empty()) {
int nodCurent = coada.front();
coada.pop();
for (auto vecin: vecini[nodCurent]) {
/// daca nodul este nevizitat si muchia nu a fost folosit de alt drum (nu are fluxul la capacitatea maxima)
if (tati[vecin] == -1 && flux[nodCurent][vecin] < capacitate[nodCurent][vecin]) {
coada.push(vecin);
tati[vecin] = nodCurent;
/// verific daca am ajuns la nodul destinatie
if (vecin == nodDestinatie) {
drum = true;
break;
}
}
}
}
return drum;
}
int main() {
int nrNoduri;
in >> nrNoduri;
int nodSursa = 2 * nrNoduri + 1, nodDestinatie = 2 * nrNoduri + 2;
/// in vectorul vecini retin toate posibilile noduri adiacente ale fiecarui nod
vector<vector<int>> vecini(2 * nrNoduri + 3);
/// in vectorul capacitate retin capacitatea maxima pe care o poate avea fiecare muchie
vector<vector<int>> capacitate(2 * nrNoduri + 3, vector<int>(2 * nrNoduri + 3, 0));
/// voi folosi 2 "seturi" de noduri: de la 1 la N si de la N + 1 la 2 * N
/// nodurile 1..N reprezinta aceleasi noduri ca N + 1..2 * N (1 == N + 1, 2 == N + 2 ...)
/// primul set de noduri (1..N) sunt noduri din care se pleaca spre nodul destinatie
/// al doilea set de noduri (N + 1 .. 2 * N) sunt noduri din care se ajunge in nodul sursa
for (int i = 1; i <= nrNoduri; i++) {
int gradInterior, gradExterior;
in >> gradExterior >> gradInterior;
capacitate[nodSursa][i] = gradExterior;
vecini[i].push_back(nodSursa);
vecini[nodSursa].push_back(i);
capacitate[i + nrNoduri][nodDestinatie] = gradInterior;
vecini[i + nrNoduri].push_back(nodDestinatie);
vecini[nodDestinatie].push_back(i + nrNoduri);
}
for (int i = 1; i <= nrNoduri; i++) {
for (int j = nrNoduri + 1; j <= 2 * nrNoduri; j++) {
/// daca nu se formeaza un ciclu (de la 1 la N + 1) atunci ar putea exista o muchie intre cele 2 noduri
if (j - nrNoduri != i) {
capacitate[i][j] = 1;
vecini[i].push_back(j);
vecini[j].push_back(i);
}
}
}
/// !!! folosim alg Edmonds-Karp !!!
vector<vector<int>> flux(2 * nrNoduri + 3, vector<int>(2 * nrNoduri + 3, 0));
int fluxTotal = 0;
bool drum = true;
while (drum) {
/// folosesc un vector de tati pentru a reconstitui drumul gasit
vector<int> tati(2 * nrNoduri + 3, -1);
drum = BFS(nodSursa, nodDestinatie, tati, vecini, nrNoduri, flux, capacitate);
if (drum) {
/// refac drumul si determin bottleneck-ul drumului
int bottleneck = INT_MAX;
int nodActual = nodDestinatie;
while (tati[nodActual] != 0) {
int tata = tati[nodActual];
if(capacitate[tata][nodActual] - flux[tata][nodActual] < bottleneck)
bottleneck = capacitate[tata][nodActual] - flux[tata][nodActual];
nodActual = tata;
}
/// actualizez fluxul maxim
fluxTotal += bottleneck;
/// actualizez fluxul fiecarei muchii din drumul gasit
nodActual = nodDestinatie;
while (tati[nodActual] != 0) {
int tata = tati[nodActual];
flux[tata][nodActual] += bottleneck;
flux[nodActual][tata] -= bottleneck;
nodActual = tata;
}
}
}
out << fluxTotal << endl;
for (int i = 1; i <= nrNoduri; i++) {
for (int j = nrNoduri + 1; j <= 2 * nrNoduri; j++) {
if (flux[i][j] > 0) {
out << i << " " << j - nrNoduri << endl;
}
}
}
return 0;
}