Cod sursa(job #1976684)

Utilizator crushackPopescu Silviu crushack Data 3 mai 2017 23:36:54
Problema Flux maxim de cost minim Scor 70
Compilator cpp Status done
Runda Arhiva educationala Marime 4.43 kb
#include <bits/stdc++.h>

using namespace std;

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

	T flow_val_;
	T cost_val_;

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

	vector<T> real_dist;
	vector<T> dist;
	vector<size_t> parent;
	priority_queue<pair<int, int>, vector<pair<int, int>>, greater<pair<int, int>>> q;

public:

	MaxFlowMinimalCost(size_t n) 
			: graph_(n + 1), 
			  capacity_(n + 1, vector<T>(n + 1)), 
			  flow_(n + 1, vector<T>(n + 1)), 
			  cost_(n + 1, vector<T>(n + 1)),
			  dist(n + 1),
			  real_dist(n + 1),
			  parent(n + 1) {}

	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<T> bellman_ford(size_t start) {
		queue<size_t> q;
		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];

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

			in_queue[node] = false;
		}

		return dist;
	}

	vector<size_t> dijkstra(size_t start, size_t finish, vector<T>& bellman_cost) {
		fill(dist.begin(), dist.end(), INF);
		parent[finish] = 0;
		dist[start] = 0;
		real_dist[start] = 0;

		q.push({dist[start], start});

		while (!q.empty()) {
			int cost = q.top().first;
			int node = q.top().second;

			q.pop();

			if (dist[node] != cost) {
				continue;
			}

			for (size_t neigh : graph_[node]) {
				if (flow_[node][neigh] < capacity_[node][neigh]) {
					int new_dist = dist[node] + cost_[node][neigh] + bellman_cost[node] - bellman_cost[neigh];

					if (new_dist < dist[neigh]) {
						dist[neigh] = new_dist;
						real_dist[neigh] = real_dist[node] + cost_[node][neigh];
						parent[neigh] = node;

						q.push({dist[neigh], neigh});
					}
				}
			}
		}

		bellman_cost = real_dist;

		return parent;
	}


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

		auto bellman_cost = bellman_ford(start);

		while (true) {
			auto parent = dijkstra(start, finish, bellman_cost);

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

			T fmin = INF;

			for (size_t node = finish; node != start; node = parent[node]) {
				fmin = min(fmin, capacity_[parent[node]][node] - flow_[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 += real_dist[finish] * fmin;
		}

		flow_val_ = flow;	
		cost_val_ = cost;

		return {flow, cost};
	}
};

template <int LMAX=256>
class InputParser {
	char buffer[LMAX];
	char *iter;
public:

	InputParser() {
		buffer[0] = 0;
		iter = buffer;
	}

	int nextInt() {
		if (*iter == 0) {
			iter = fgets(buffer, LMAX, stdin);
			buffer[strlen(buffer) - 1] = 0;
		}

		
		int number = 0;
		for (; *iter && !isdigit(*iter) && *iter != '-'; ++ iter) continue;

		bool sign = false;

		if (*iter == '-') {
			sign = true;
			++ iter;
		}

		for (; *iter && isdigit(*iter); ++ iter) {
			number = number * 10 + *iter - '0';
		}

		for (; *iter && !isdigit(*iter) && *iter != '-'; ++ iter) continue;

		return sign ? -number : number;
	}

};

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

	int n, m, start, finish;

	InputParser<256> parser;

	n = parser.nextInt();
	m = parser.nextInt();
	start = parser.nextInt();
	finish = parser.nextInt();

	MaxFlowMinimalCost<int> flow(n);

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

		x = parser.nextInt();
		y = parser.nextInt();
		cap = parser.nextInt();
		cost = parser.nextInt();
		flow.add_edge(x, y, cap, cost);
	}

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

	cout << res.second << endl;

	return 0;
}