Pagini recente » Cod sursa (job #46754) | Cod sursa (job #649353) | Cod sursa (job #1057977) | Cod sursa (job #1585666) | Cod sursa (job #2987494)
#include <fstream>
#include <vector>
#include <queue>
#include <cstring>
using namespace std;
ifstream fin("fmcm.in");
ofstream fout("fmcm.out");
const int NMAX = 350, INF = 0x3f3f3f3f;
vector<int> graf[NMAX + 5];
queue<int> coada;
int N, M, capacitate[NMAX + 5][NMAX + 5], flow[NMAX + 5][NMAX + 5], tata_de[NMAX + 5], cost[NMAX + 5][NMAX + 5], dist[NMAX + 5];
int startNod, endNod;
// Retinem in aceasta structura nodul vecin cu care se ajunge cu dist in endNod
// De asemenea, supraincarcam operatorul < pentru a-l face min heap
struct elemHeap
{
int dist, nod;
bool operator<(const elemHeap& otherElem)const
{
return dist > otherElem.dist;
}
};
// Implementare Bellman-Ford optimizat cu coada a.k.a SPFA
bool bellmanFord()
{
memset(tata_de, 0, sizeof tata_de);
memset(dist, INF, sizeof dist);
coada.push(startNod);
dist[startNod] = 0;
while (!coada.empty())
{
int nod_curent = coada.front();
coada.pop();
for (int i = 0; i < graf[nod_curent].size(); i++)
{
int vecin = graf[nod_curent][i];
if (capacitate[nod_curent][vecin] - flow[nod_curent][vecin] > 0 && dist[vecin] > dist[nod_curent] + cost[nod_curent][vecin])
{
dist[vecin] = dist[nod_curent] + cost[nod_curent][vecin];
tata_de[vecin] = nod_curent;
coada.push(vecin);
}
}
}
return dist[endNod] != INF;
}
int main()
{
fin >> N >> M >> startNod >> endNod;
for (int i = 0; i < M; i++)
{
int from, to, capacity, cost_muchie;
fin >> from >> to >> capacity >> cost_muchie;
graf[from].push_back(to);
graf[to].push_back(from);
capacitate[from][to] = capacity;
cost[from][to] = cost_muchie;
// Ca sa ne intoarcem ca si cum nu am fi fost prin nod
cost[to][from] = -cost_muchie;
}
int max_flow = 0;
while (bellmanFord())
{
// Optimizare: luam vecinii cu distantele cele mai mici pana la endNod
priority_queue<elemHeap> bestVecini;
for (int i = 0; i < graf[endNod].size(); i++)
{
int vecin = graf[endNod][i];
int distanta = dist[vecin] + cost[vecin][endNod];
bestVecini.push({distanta, vecin});
}
while (!bestVecini.empty())
{
int fluxMin, vecin = bestVecini.top().nod, dist_la_final = bestVecini.top().dist;
// startNod nu are tata, dar este un vecin bun
if (tata_de[vecin] == 0 && vecin != startNod)
continue;
if (capacitate[vecin][endNod] - flow[vecin][endNod] <= 0)
continue;
if (vecin == startNod)
{
fluxMin = capacitate[startNod][endNod] - flow[startNod][endNod];
flow[startNod][endNod] += fluxMin;
flow[endNod][startNod] -= fluxMin;
max_flow += fluxMin * dist_la_final;
bestVecini.pop();
continue;
}
fluxMin = capacitate[vecin][endNod] - flow[vecin][endNod];
while (vecin != startNod)
{
fluxMin = min(fluxMin, capacitate[tata_de[vecin]][vecin] - flow[tata_de[vecin]][vecin]);
vecin = tata_de[vecin];
}
if (fluxMin == 0)
continue;
vecin = bestVecini.top().nod;
flow[vecin][endNod] += fluxMin;
flow[endNod][vecin] -= fluxMin;
while (vecin != startNod)
{
flow[tata_de[vecin]][vecin] += fluxMin;
flow[vecin][tata_de[vecin]] -= fluxMin;
vecin = tata_de[vecin];
}
max_flow += fluxMin * dist_la_final;
bestVecini.pop();
}
}
fout << max_flow << "\n";
return 0;
}