Cod sursa(job #1976624)

Utilizator crushackPopescu Silviu crushack Data 3 mai 2017 21:41:22
Problema Flux maxim de cost minim Scor 50
Compilator cpp Status done
Runda Arhiva educationala Marime 2.58 kb
#include <bits/stdc++.h>

using namespace std;

template <class T, T INF=0x3f3f3f3f>
class MaxFlowMinimalCost {
	typedef vector<vector<int>> Graph;
	typedef unordered_map<size_t, unordered_map<size_t, T>> SparseMatrix;

	T flow_val_;
	T cost_val_;

	Graph graph_;
	SparseMatrix capacity_;
	SparseMatrix flow_;
	SparseMatrix cost_;

public:

	MaxFlowMinimalCost(size_t n) {
		graph_.resize(n + 1);
	}

	virtual void add_edge(size_t x, size_t y, T capacity, T cost) {
		graph_[x].push_back(y);
		graph_[y].push_back(x);

		capacity_[x][y] += capacity;
		capacity_[y][x] += 0;

		cost_[x][y] = cost;
		cost_[y][x] = -cost;
	}

	SparseMatrix get_flow() {
		return flow_;
	}

	vector<size_t> bellmanFord(int start) {
		queue<size_t> q;

		vector<size_t> parent(graph_.size(), 0);
		vector<T> dist(graph_.size(), INF);

		vector<bool> in_queue(graph_.size(), false);

		q.push(start);
		in_queue[start] = true;
		dist[start] = 0;

		while (!q.empty()) {
			size_t node = q.front(); q.pop();

			for (size_t neigh : graph_[node]) {
				if (flow_[node][neigh] < capacity_[node][neigh] && dist[node] + cost_[node][neigh] < dist[neigh]) {
					dist[neigh] = dist[node] + cost_[node][neigh];
					parent[neigh] = node;

					if (!in_queue[neigh]) {
						in_queue[neigh] = true;
						q.push(neigh);
					}
				}
			}

			in_queue[node] = false;
		}

		return parent;
	}


	pair<T, T> do_flow(size_t start, size_t finish) {
		T flow = 0;
		T cost = 0;

		while (true) {
			auto parent = bellmanFord(start);

			if (parent[finish] == 0) {
				break;
			}

			T fmin = INF;
			T cmin = 0;

			for (size_t node = finish; node != start; node = parent[node]) {
				fmin = min(fmin, capacity_[parent[node]][node] - flow_[parent[node]][node]);
				cmin += cost_[parent[node]][node];
			}

			if (fmin == 0) {
				continue;
			}

			for (size_t node = finish; node != start; node = parent[node]) {
				flow_[parent[node]][node] += fmin;
				flow_[node][parent[node]] -= fmin;
			}

			flow += fmin;
			cost += cmin * fmin;
		}

		flow_val_ = flow;	
		cost_val_ = cost;

		return {flow, cost};
	}
};

int main() {
	freopen("fmcm.in", "r", stdin);
	freopen("fmcm.out", "w", stdout);

	int n, m, start, finish;

	cin >> n >> m >> start >> finish;

	MaxFlowMinimalCost<int> flow(n);

	for (int i = 0; i < m; ++ i) {
		int x, y, cap, cost;

		cin >> x >> y >> cap >> cost;
		flow.add_edge(x, y, cap, cost);
	}

	auto res = flow.do_flow(start, finish);

	// cerr << res.first << endl;
	cout << res.second << endl;

	return 0;
}