Cod sursa(job #3293881)

Utilizator andrei_C1Andrei Chertes andrei_C1 Data 12 aprilie 2025 20:39:15
Problema Flux maxim Scor 0
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 2.83 kb
#include <bits/stdc++.h>
using namespace std;

const int kInf = 1e9;

template<class T>
bool ckmin(T &x, const T &y) {
	return y < x ? x = y, true : false;
}

struct edge_t {
	int to, cap, cst;
	edge_t() {}
	edge_t(int to, int cap, int cst) : to(to), cap(cap), cst(cst) {}
};

struct node_t {
	int u, d;
	node_t() {}
	node_t(int u, int d) : u(u), d(d) {}
	bool operator < (const node_t &oth) const {
		return d > oth.d;
	}
};

struct mcmf {
	int n;
	vector<vector<int>> adj;
	vector<edge_t> edges;
	vector<int> dist, real_dist, help_dist, par;
	priority_queue<node_t> pq;
	mcmf() {}
	mcmf(int n) : n(n), adj(n), dist(n), real_dist(n), help_dist(n), par(n) {}
	void add_edge(int u, int v, int cap, int cst) {
		int m = edges.size();
		edges.emplace_back(v, cap, cst);
		edges.emplace_back(u, 0, -cst);
		adj[u].emplace_back(m);
		adj[v].emplace_back(m + 1);
	}
	void init_dist(int s) {
		queue<int> q;
		vector<bool> inq(n);
		fill(real_dist.begin(), real_dist.end(), kInf);
		real_dist[s] = 0;
		q.emplace(s);
		inq[s] = true;
		while(!q.empty()) {
			int u = q.front();
			q.pop();
			inq[u] = false;
			for(const auto &it : adj[u]) {
				auto [to, cap, cst] = edges[it];
				if(!cap) {
					continue;
				}
				if(real_dist[u] + cst < real_dist[to]) {
					real_dist[to] = real_dist[u] + cst;
					if(!inq[to]) {
						q.emplace(to);
						inq[to] = true;
					}
				}
			}
		}
	}
	bool dij(int s, int d) {
		dist = real_dist;
		fill(real_dist.begin(), real_dist.end(), kInf);
		fill(help_dist.begin(), help_dist.end(), kInf);
		real_dist[s] = 0;
		help_dist[s] = 0;
		pq.emplace(s, help_dist[s]);
		while(!pq.empty()) {
			auto [u, d] = pq.top();
			pq.pop();
			if(d != help_dist[u]) {
				continue;
			}
			for(const auto &it : adj[u]) {
				auto [to, cap, cst] = edges[it];
				if(!cap) {
					continue;
				}
				if(help_dist[u] + dist[u] + cst < help_dist[to] + dist[to]) {
					par[to] = it;
					help_dist[to] = help_dist[u] + dist[u] + cst - dist[to];
					real_dist[to] = real_dist[u] + cst;
					pq.emplace(to, help_dist[to]);
				}
			}
		}
		return help_dist[d] != kInf;
	}
	int mincost(int s, int d) {
		int res = 0;
		while(dij(s, d)) {
			int flow = kInf, cost = 0;
			for(int u = d; u != s; u = edges[par[u] ^ 1].to) {
				ckmin(flow, edges[par[u]].cap);
				cost += edges[par[u]].cst;
			}
			res += cost * flow;
			for(int u = d; u != s; u = edges[par[u] ^ 1].to) {
				edges[par[u]].cap -= flow;
				edges[par[u] ^ 1].cap += flow;
			}
		}
		return res;
	}
};

int main() {
	cin.tie(nullptr)->sync_with_stdio(false);
#ifdef INFOARENA
	freopen("fmcm.in", "r", stdin);
	freopen("fmcm.out", "w", stdout);
#endif
	int n, m, s, d;
	cin >> n >> m >> s >> d;
	s--; d--;
	mcmf graph(n);
	for(int i = 0; i < m; i++) {
		int u, v, cap, cst;
		cin >> u >> v >> cap >> cst;
		u--; v--;
		graph.add_edge(u, v, cap, cst);
	}
	graph.init_dist(s);
	cout << graph.mincost(s, d);
	return 0;
}