Pagini recente » Cod sursa (job #2536740) | Cod sursa (job #2412920) | cel_mai_mare_olimpicar_2019_oni2011_zi1 | Cod sursa (job #1682080) | Cod sursa (job #2957664)
#include <iostream>
#include <fstream>
#include <vector>
#include <queue>
#include <climits>
//facem un ford fulkerson obisnuit. Complexitate O(mL); m = nr de muchii; L = capacitatea minima a uneti taieturi
using namespace std;
ifstream in("maxflow.in");
ofstream out("maxflow.out");
int n, m, fluxMaxim;
vector<vector<int>> ramas;
vector<int> visited, dad;
queue<int> coada;
bool construiesteDrum()
{
int i, nodCurent;
while(!coada.empty())
coada.pop();
for(i = 1; i <= n; i++)
{
dad[i] = 0;
visited[i] = 0;
}
coada.push(1); //pornim de la nodul 1 pt ca ala e nodul de start
visited[1] = 1;
while(!coada.empty())
{
nodCurent = coada.front();
coada.pop();
if (nodCurent == n) //daca am ajuns la n care e destinatia inseamna ca am reusit sa creem un drum
return true;
for(i = 1; i <= n; i++) //parcurgem toate nodurile si vedem daca se poate ajunge din nodul curent in respectivul nod (adica sa nu fie vizitat si sa mai avem capacitate ramasa)
if(ramas[nodCurent][i] > 0 && visited[i] == 0)
{
visited[i] = 1;
dad[i] = nodCurent;
coada.push(i);
}
}
return false; //daca se ajunge aici inseamna ca if(nodCurent == n) nu a fost apelat, deci nu s-a ajuns pana la destinatie, deci nu am reusit sa creem un drum
}
void calculeazaFluxMax()
{
int i, fiu, nodCurent, j, bootleNeck;
vector<int> drum;
while(construiesteDrum()) //daca nu mai gasim un drum ne oprim
{
for(i = 1; i < n; i++) //incercam sa reconstruim drumurile
{
if(ramas[i][n] > 0 && visited[i] == 1) //inseamna ca din nodul i la care suntem acuma s-a transportat o anumita cantitate in nodul final
{
fiu = i;
drum.clear(); //daca nu facem asta ramane din forul anterior
drum.push_back(n);
drum.push_back(fiu);
nodCurent = dad[fiu];
while (nodCurent != 1) //mergem inapoi pe traseu si reconstruim drumul
{
drum.push_back(nodCurent);
nodCurent = dad[nodCurent];
}
drum.push_back(1);
bootleNeck = INT_MAX;
for(j = drum.size() - 1; j >= 1; j--) //parcurgem pe invers pt ca noi in drum am pus elementele pornind de la destinatie spre start
bootleNeck = min(bootleNeck, ramas[drum[j]][drum[j - 1]]);
fluxMaxim += bootleNeck;
for(j = drum.size() - 1; j >= 1; j--)
{
ramas[drum[j]][drum[j - 1]] -= bootleNeck; //scadem capacitatea ramase pt drumurile prin care am trecut
ramas[drum[j - 1]][drum[j]] += bootleNeck; //in cazul drumurilor reversed crestem aceasta capacitate
}
}
}
}
}
int main()
{
int i, nod1, nod2, capacitate;
in >> n >> m;
ramas.resize(n + 1);
visited.resize(n + 1);
dad.resize(n + 1);
for(i = 1; i <= n; i++)
ramas[i].resize(n + 1, 0);
for(i = 1; i <= m; i++)
{
in >> nod1 >> nod2 >> capacitate;
ramas[nod1][nod2] = capacitate;
}
calculeazaFluxMax();
out << fluxMaxim;
return 0;
}