Pagini recente » Cod sursa (job #403357) | Cod sursa (job #494709) | Cod sursa (job #7109) | Cod sursa (job #2035571) | Cod sursa (job #2960595)
#include<iostream>
#include <fstream>
#include <vector>
#include <queue>
using namespace std;
const int inf = 1e9;
int n, m, sursa, dest;
vector<vector<int>> graf;
int capacitate[400][400];
int cost[400][400];//costul muchiei i,j
int distanta[400];//distanta dela sursa la nodul i
int new_dist[400];
bool in_coada[400];
vector<int> parinte;
// aplicam algoritmul lui Bellman-Ford,
// calculam valorile vectorului dist.
// petru a folosi dijkstra astfel:
// calculam distanta minima de la sursa la nodul i
// ficarui arc a->b cu costul c va avea noul cost
// c + dist a - dist b astfel incat sa
// nu mai exista arce cu cost negativ
void aflare_distanta_minima() {
for (int i = 1; i <= n; ++i)
distanta[i] = inf;
distanta[sursa] = 0;
queue<int> q;
q.push(sursa);
in_coada[sursa] = true;
while (!q.empty()) {
int curr = q.front();
q.pop();
in_coada[curr] = true;
for (int node: graf[curr]) {
if (capacitate[curr][node] != 0) {
if (distanta[curr] + cost[curr][node] < distanta[node]) {
distanta[node] = distanta[curr] + cost[curr][node];
if (!in_coada[node]) {
q.push(node);
in_coada[node] = true;
}
}
}
}
}
}
void flux(int &cflux, int &ccost) {
for (int i = 1; i <= n; ++i) {
parinte[i] = -1;
new_dist[i] = inf;
}
// distanta, nod
priority_queue<pair<int, int>> q;
q.push({0, sursa});
new_dist[sursa] = 0;
parinte[sursa] = 0;
while (!q.empty()) {
int curr_dist = -q.top().first;
int curr_node = q.top().second;
q.pop();
if (curr_dist != new_dist[curr_node])
continue;
for (int node: graf[curr_node]) {
if (capacitate[curr_node][node] != 0) {
int dist = cost[curr_node][node] + distanta[curr_node] - distanta[node];
int dist_c = curr_dist + dist;
if (dist_c < new_dist[node]) {
new_dist[node] = dist_c;
parinte[node] = curr_node;
q.push({-dist_c, node});
}
}
}
}
int c = 0;
int flux = inf;
if (parinte[dest] != -1) {
int node = dest;
while (node != sursa) {
flux = min(flux, capacitate[parinte[node]][node]);
c += cost[parinte[node]][node];
node = parinte[node];
}
node = dest;
while (node != sursa) {
capacitate[node][parinte[node]] += flux;
capacitate[parinte[node]][node] -= flux;
node = parinte[node];
}
for (int i = 1; i <= n; ++i)
distanta[i] = new_dist[i];
cflux = flux;
ccost = c * flux;
} else {
cflux = 0;
ccost = 0;
}
}
int main() {
ifstream fin("fmcm.in");
ofstream fout("fmcm.out");
fin >> n >> m >> sursa >> dest;
graf.resize(n + 1);
parinte.resize(n + 1);
//initializare lista de adiacenta, capacitate si cost
while (m--) {
int x, y, cap, cos;
fin >> x >> y >> cap >> cos;
cost[x][y] = cos;
cost[y][x] = -cos;
capacitate[x][y] = cap;
capacitate[y][x] = 0;
graf[x].push_back(y);
graf[y].push_back(x);
}
//calculam fluxum maxim de cost minim
aflare_distanta_minima();
int current_flux = 0, current_cost = 0;
int total_cost = 0;
flux(current_flux, current_cost);
total_cost += current_cost;
while (current_flux) {
flux(current_flux, current_cost);
total_cost += current_cost;
}
fout << total_cost << "\n";
return 0;
}