Pagini recente » Cod sursa (job #3258397) | Diferente pentru documentatie/arhiva-educationala intre reviziile 8 si 5 | Cod sursa (job #2532868) | Cod sursa (job #83064) | Cod sursa (job #3222509)
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
ifstream fin("fmcm.in");
ofstream fout("fmcm.out");
const int NMAX = 350;
const int INF = 1e9;
struct edge {
int to, cap, flow, cost, rid;
};
int n, m, s, t;
vector<edge> g[NMAX + 1];
int dist[NMAX + 1];
ll costDist[NMAX + 1];
int potential[NMAX + 1];
bool inQueue[NMAX + 1];
bool vis[NMAX + 1];
int ptrToParent[NMAX + 1];
int flow[NMAX + 1];
void add_edge(int u, int v, int c, int z) {
int r1 = g[v].size();
int r2 = g[u].size();
g[u].push_back({v, c, 0, z, r1});
g[v].push_back({u, 0, 0, -z, r2});
}
void compute_potentials(int s) {
//run bellman ford to calculate the distances
//set potential equal to the distances
for (int i = 1; i <= n; i++)
potential[i] = INF;
queue<int> q;
q.push(s);
potential[s] = 0;
while (!q.empty()) {
int node = q.front();
q.pop();
inQueue[node] = false;
for (auto &it : g[node]) {
if (it.cap <= it.flow) continue; //ignore edges from residual graph
if (potential[node] + it.cost < potential[it.to])
potential[it.to] = potential[node] + it.cost;
if (!inQueue[it.to]) {
inQueue[it.to] = true;
q.push(it.to);
}
}
}
}
int dijkstra(int s, int t) {
for (int i = 1; i <= n; i++) {
dist[i] = INF;
flow[i] = 0;
vis[i] = 0;
ptrToParent[i] = 0;
}
dist[s] = 0;
flow[s] = INF;
//heap (dist, node)
priority_queue<pair<int, int>, vector<pair<int, int>>, greater<pair<int, int>>> pq;
pq.push(make_pair(0, s));
while (!pq.empty()) {
int node = pq.top().second;
pq.pop();
if (vis[node]) continue;
vis[node] = 1;
for (auto &it : g[node]) {
if (it.flow < it.cap && !vis[it.to] && dist[it.to] > dist[node] - potential[it.to] + potential[node] + it.cost) {
dist[it.to] = dist[node] - potential[it.to] + potential[node] + it.cost;
flow[it.to] = min(flow[node], it.cap - it.flow);
ptrToParent[it.to] = it.rid;
pq.push(make_pair(dist[it.to], it.to));
}
}
}
//return the new flow
return flow[t];
}
pair<int, ll> min_cost_max_flow(int s, int t) {
int flow = 0, newFlow = 0;
ll cost = 0;
while (newFlow = dijkstra(s, t)) {
for (int i = 1; i <= n; i++)
dist[i] += potential[i] - potential[s];
for (int i = 1; i <= n; i++)
potential[i] = dist[i];
flow += newFlow;
cost += 1LL * newFlow * dist[t];
int node = t;
while (node != s) {
g[node][ptrToParent[node]].flow -= newFlow;
g[g[node][ptrToParent[node]].to][g[node][ptrToParent[node]].rid].flow += newFlow;
node = g[node][ptrToParent[node]].to;
}
}
return make_pair(flow, cost);
}
void read() {
fin >> n >> m >> s >> t;
for (int i = 1; i <= m; i++) {
int u, v, c, z;
fin >> u >> v >> c >> z;
add_edge(u, v, c, z);
}
}
void solve() {
compute_potentials(s);
fout << min_cost_max_flow(s, t).second << '\n';
}
int main() {
read();
solve();
return 0;
}