Cod sursa(job #813554)

Utilizator ahmed.abdraboahmed.abdrabo ahmed.abdrabo Data 15 noiembrie 2012 18:43:22
Problema Flux maxim de cost minim Scor 70
Compilator cpp Status done
Runda Arhiva educationala Marime 2.9 kb
#include <algorithm>
#include <cassert>
#include <cstdio>
#include <cstring>
#include <queue>
#include <set>
#include <vector>

using namespace std;

inline int next_int() {
	int n = 0, sign = 1;
	char c = getchar_unlocked();
	while (!('0' <= c && c <= '9')) {
		sign *= c == '-' ? -1 : 1;
		c = getchar_unlocked();
	}
	while ('0' <= c && c <= '9') {
		n = n * 10 + c - '0';
		c = getchar_unlocked();
	}
	return sign * n;
}

const int INF = 1e9;
const int MAX_V = 350;
const int MAX_E = 12500 + 12500;

int V, E, min_cost, max_flow, path_cost, path_flow, where;
int from[MAX_E], to[MAX_E], capacity[MAX_E], cost[MAX_E];
int e_begin[MAX_V], e_next[MAX_E];
int dist[MAX_V], prev[MAX_V];
bool seen[MAX_V];

inline void add_edge(const int & a, const int & b, const int & c, const int & d) {
	from[E] = a; to[E] = b; capacity[E] = c; cost[E] = +d; E++;
	from[E] = b; to[E] = a; capacity[E] = 0; cost[E] = -d; E++;
}

inline void run(const int & source, const int & sink) {
	for (int v = 0; v < V; v++) {
		dist[v] = INF;
		e_begin[v] = -1;
	}
	dist[source] = 0;
	for (int e = 0; e < E; e++) {
		e_next[e] = e_begin[from[e]];
		e_begin[from[e]] = e;
	}
	for (int v = 0; v < V; v++) {
		for (int e = 0; e < E; e++) {
			if (dist[from[e]] < INF && capacity[e] > 0 && dist[from[e]] + cost[e] < dist[to[e]]) {
				dist[to[e]] = dist[from[e]] + cost[e];
			}
		}
	}
	path_cost = dist[sink];
	while (true) {
		for (int e = 0; e < E; e++) {
			cost[e] += dist[from[e]] - dist[to[e]];
		}
		for (int v = 0; v < V; v++) {
			prev[v] = -1;
			seen[v] = false;
			dist[v] = INF;
		}
		dist[source] = 0;
		set<pair<int, int> > Q;
		Q.insert(make_pair(0, source));
		while (!Q.empty()) {
			int current_dist = Q.begin()->first;
			int current_where = Q.begin()->second;
			Q.erase(Q.begin());
			if (!seen[current_where]) {
				seen[current_where] = true;
				for (int e = e_begin[current_where]; e != -1; e = e_next[e]) {
					if (capacity[e] > 0 && current_dist + cost[e] < dist[to[e]]) {
						Q.erase(make_pair(dist[to[e]], to[e]));
						Q.insert(make_pair(current_dist + cost[e], to[e]));
						dist[to[e]] = current_dist + cost[e];
						prev[to[e]] = e;
					}
				}
			}
		}
		if (dist[sink] == INF) {
			break;
		}
		for (where = sink, path_flow = INF; where != source; where = from[prev[where]]) {
			path_flow = min(path_flow, capacity[prev[where]]);
		}
		for (where = sink; where != source; where = from[prev[where]]) {
			capacity[prev[where]] -= path_flow;
			capacity[prev[where] ^ 1] += path_flow;
		}
		path_cost += dist[sink];
		min_cost += path_flow * path_cost;
		max_flow += path_flow;
	}
}

int main() {
	freopen("fmcm.in", "r", stdin);
	freopen("fmcm.out", "w", stdout);
	V = next_int();
	int m = next_int();
	int s = next_int() - 1;
	int d = next_int() - 1;
	for (int i = 0; i < m; i++) {
		int x = next_int() - 1;
		int y = next_int() - 1;
		int c = next_int();
		int z = next_int();
		add_edge(x, y, c, z);
	}
	run(s, d);
	printf("%d\n", min_cost);
	return 0;
}