Pagini recente » Cod sursa (job #1338048) | Cod sursa (job #488466) | Cod sursa (job #685006) | Cod sursa (job #893624) | Cod sursa (job #2960262)
#include <climits>
#include <fstream>
#include <iostream>
#include <queue>
#include <vector>
using namespace std;
ifstream fin("fmcm.in");
ofstream fout("fmcm.out");
int n, m, source, dest, costMin;
vector<vector<int> > adjList, capac, cost_arc;
vector<int> cost_init, costuri, cost_actual;
bool Dijkstra() {
int i, curr_node, curr_node_dist, j, new_node, new_cost, capMin = INT_MAX, newDest = dest, costActual = 0;
priority_queue<pair<int, int>, vector<pair<int, int> >, greater<pair<int, int> > > pq;
vector<int> parinte;
parinte.clear();
parinte.resize(n + 1);
for (i = 1; i <= n; i++)
costuri[i] = INT_MAX;
costuri[source] = 0;
cost_actual[source] = 0;
pq.push(make_pair(0, source));
while(!pq.empty()) {
curr_node = pq.top().second;
curr_node_dist = pq.top().first;
pq.pop();
if(costuri[curr_node] == curr_node_dist)
for(j = 0; j < adjList[curr_node].size(); j++) {
new_node = adjList[curr_node][j];
// Mai este capacitate de flux ramasa.
if(capac[curr_node][new_node] > 0) {
new_cost = costuri[curr_node] + cost_arc[curr_node][new_node] + cost_init[curr_node] - cost_init[new_node];
if (new_cost < costuri[new_node]) {
costuri[new_node] = new_cost;
cost_actual[new_node] = cost_actual[curr_node] + cost_arc[curr_node][new_node];
parinte[new_node] = curr_node;
pq.push(make_pair(costuri[new_node], new_node));
}
}
}
}
for (i = 1; i <= n; i++)
cost_init[i] = cost_actual[i];
// Nu s-a ajuns la destinatie.
if (costuri[dest] == INT_MAX)
return false;
while (newDest != source) {
capMin = min(capMin, capac[parinte[newDest]][newDest]);
costActual += cost_arc[parinte[newDest]][newDest];
newDest = parinte[newDest];
}
costMin += capMin * cost_actual[dest];
newDest = dest;
// Parcurg din nou drumul de ameliorare.
while(newDest != source) {
// Scad capacitatea pentru drumurile parcurse.
capac[parinte[newDest]][newDest] -= capMin;
// Pentru muchia inversa, maresc capacitatea.
capac[newDest][parinte[newDest]] += capMin;
newDest = parinte[newDest];
}
return true;
}
void BellmanFord() {
int i, curr_node, j, new_node;
queue<int> q;
vector<int> is_in_q(n + 1, 0);
for(i = 1; i <= n; i++)
cost_init[i] = INT_MAX;
cost_init[source] = 0;
q.push(source);
is_in_q[source] = 1;
while (!q.empty()) {
curr_node = q.front();
q.pop();
// Nodul nu mai e in queue.
is_in_q[curr_node] = 0;
for(j = 0; j < adjList[curr_node].size(); j++) {
new_node = adjList[curr_node][j];
if(capac[curr_node][new_node])
if(cost_init[curr_node] + cost_arc[curr_node][new_node] < cost_init[new_node]) {
cost_init[new_node] = cost_init[curr_node] + cost_arc[curr_node][new_node];
// Adaug in queue daca nu e.
if (is_in_q[new_node] == 0) {
is_in_q[new_node] = 1;
q.push(new_node);
}
}
}
}
}
int main() {
int i, nod1, nod2, cap, cost;
fin >> n >> m >> source >> dest;
adjList.resize(n + 1);
capac.resize(n + 1);
cost_arc.resize(n + 1);
costuri.resize(n + 1, 0);
cost_actual.resize(n + 1, 0);
cost_init.resize(n + 1, 0);
for(i = 0; i <= n; i++) {
capac[i].resize(n + 1, 0);
cost_arc[i].resize(n + 1, 0);
}
for (int i = 0; i < m; i++) {
fin >> nod1 >> nod2 >> cap >> cost;
adjList[nod1].push_back(nod2);
adjList[nod2].push_back(nod1);
capac[nod1][nod2] = cap;
cost_arc[nod1][nod2] = cost;
// Costul arcului invers este minusul costului arcului.
cost_arc[nod2][nod1] = -cost;
}
BellmanFord();
// Atata timp cat mai exista drumuri de ameliorare, inseamna ca mai putem adauga flux.
while (Dijkstra());
fout << costMin;
return 0;
}