Pagini recente » Cod sursa (job #2025034) | Cod sursa (job #756742) | Cod sursa (job #65087) | Cod sursa (job #355003) | Cod sursa (job #2884085)
#include <iostream>
#include <vector>
#include <algorithm>
#include <string>
#include <cassert>
#include <algorithm>
#include <set>
#include <iomanip>
#include <queue>
#include <deque>
#include <unordered_set>
#include <unordered_map>
#include <functional>
#include <cmath>
#include <map>
#include <random>
#include <chrono>
#include <cstdio>
bool home = true;
using namespace std;
typedef long long ll;
const int FN = 350 + 7;
const int FM = 12500 + 7;
const int INF = (int)1e9 + 7;
struct Edge {
int to;
int cap;
int cost;
};
int fn, fm, fs, fd;
Edge edges[2 * FM];
int inds[FN][FN], dim[FN], the_cost[FN][FN];
int best[FN], init_best[FN];
int parrent_edge[FN];
bool inq[FN];
queue<int> fq;
priority_queue<pair<int, int>> fpq;
void setup(int n, int s, int d) {
fn = n;
fm = 0;
fs = s;
fd = d;
for (int i = 0; i < fn; i++) {
dim[i] = 0;
}
}
void addEdge(int a, int b, int cap, int cost) {
assert(1 <= a && a <= fn);
assert(1 <= b && b <= fn);
inds[a][dim[a]++] = fm;
inds[b][dim[b]++] = fm + 1;
edges[fm++] = { b, cap, cost };
edges[fm++] = { a, 0, -cost };
}
void bell() {
assert(fq.empty());
for (int i = 1; i <= fn; i++) best[i] = INF, inq[i] = 0;
inq[fs] = 1;
best[fs] = 0;
fq.push(fs);
while (!fq.empty()) {
int a = fq.front();
fq.pop();
inq[a] = 0;
for (int _ = 0; _ < dim[a]; _++) {
int i = inds[a][_];
if (edges[i].cap) {
int b = edges[i].to, cost = edges[i].cost;
if (best[a] + cost < best[b]) {
best[b] = best[a] + cost;
parrent_edge[b] = i;
if (!inq[b]) inq[b] = 1, fq.push(b);
}
}
}
}
}
void dij() {
for (int a = 1; a <= fn; a++) {
init_best[a] = best[a];
for (int _ = 0; _ < dim[a]; _++) {
if (!edges[inds[a][_]].cap) continue;
int b = edges[inds[a][_]].to;
int cost = edges[inds[a][_]].cost;
the_cost[a][b] = best[a] + cost - best[b];
}
}
assert(fpq.empty());
for (int i = 1; i <= fn; i++) best[i] = INF;
best[fs] = 0;
fpq.push({ 0, fs });
while (!fpq.empty()) {
pair<int, int> tp = fpq.top();
fpq.pop();
int a = tp.second;
int _a_ = -tp.first;
if (_a_ != best[a]) continue;
for (int _ = 0; _ < dim[a]; _++) {
int i = inds[a][_];
if (edges[i].cap) {
int b = edges[i].to;
if (best[a] + the_cost[a][b] < best[b]) {
best[b] = best[a] + the_cost[a][b];
parrent_edge[b] = i;
fpq.push({ -best[b], b });
}
}
}
}
for (int a = 1; a <= fn; a++) {
best[a] = best[a] - init_best[fs] + init_best[a];
}
}
pair<ll, ll> get() {
ll flow = 0, cost = 0;
bell();
while (1) {
dij();
int coef = best[fd];
if (coef >= INF) break;
int mn = INF;
int vertex = fd;
while (vertex != fs) {
int i = parrent_edge[vertex];
assert(edges[i].to == vertex);
mn = min(mn, edges[i].cap);
vertex = edges[i ^ 1].to;
}
vertex = fd;
while (vertex != fs) {
int i = parrent_edge[vertex];
assert(edges[i].to == vertex);
edges[i].cap -= mn;
edges[i ^ 1].cap += mn;
vertex = edges[i ^ 1].to;
}
flow += mn;
cost += mn * (ll)coef;
}
return { flow, cost };
}
signed main() {
//FILE* stream;
//freopen_s(&stream, "iron_man.txt", "r", stdin);
freopen("fmcm.in", "r", stdin);
freopen("fmcm.out", "w", stdout);
int n, m, s, d;
cin >> n >> m >> s >> d;
setup(n, s, d);
for (int i = 1; i <= m; i++) {
int a, b, c, d;
cin >> a >> b >> c >> d;
addEdge(a, b, c, d);
}
auto fl = get();
//cout << fl.first << "\n";
cout << fl.second << "\n";
}