Cod sursa(job #1469980)

Utilizator mouse_wirelessMouse Wireless mouse_wireless Data 10 august 2015 01:19:58
Problema Flux maxim de cost minim Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 3.97 kb
#include <cstdio>
#include <cstdlib>
#include <cassert>
#include <vector>
#include <queue>
#include <cstring>
#include <set>
#include <cctype>
using namespace std;

#ifdef INFOARENA
#define ProblemName "fmcm"
#endif

#define MCONCAT(A, B) A B
#ifdef ProblemName
#define InFile MCONCAT(ProblemName, ".in")
#define OuFile MCONCAT(ProblemName, ".out")
#else
#define InFile "fis.in"
#define OuFile "fis.out"
#endif

template <class T> void readNum(T &nr) {
	nr = 0;
	T sign = 1;
	char c;
	while (!isdigit(c = getchar()))
		(c == '-') && (sign = -1);
	do {
		nr = nr * 10 + c - '0';
	} while (isdigit(c = getchar()));
	nr *= sign;
}

class graph {
private:
	vector< vector<int> > ngh;
	vector< vector<int> > F;
	vector< vector<int> > C;
	vector< vector<int> > W;
	int source, sink;
public:
	graph(int N, int _source, int _sink) {
		ngh.resize(N);
		source = _source; sink = _sink;
		F.resize(N, vector<int>(N, 0));
		C.resize(N, vector<int>(N, 0));
		W.resize(N, vector<int>(N, 0));
	}
	void insertEdge(int n1, int n2, int c, int w) {
		ngh[n1].push_back(n2);
		ngh[n2].push_back(n1);
		C[n1][n2] = c;
		W[n1][n2] = w;
		W[n2][n1] = -w;
	}
	
	void BellmanFord(vector<int> &dist) {
		int N = ngh.size();
		memset(&dist[0], 0x3F, dist.size() * sizeof(dist[0]));
		dist[source] = 0;
		queue<int> Q;
		vector<char> inQueue(N, 0);
		inQueue[source] = 1;
		Q.push(source);
		while (!Q.empty()) {
			int t = Q.front();
			Q.pop();
			inQueue[t] = 0;
			for (auto i : ngh[t])
			if (C[t][i] && dist[t] + W[t][i] < dist[i]) {
				dist[i] = dist[t] + W[t][i];
				if (!inQueue[i]) {
					inQueue[i] = 1;
					Q.push(i);
				}
			}
		}
	}
	void Dijkstra(vector<int> &adjustedDist, vector<int> &oldDist, vector<int> &realDist, vector<char> &visited, vector<int> &prev) {
		int N = ngh.size();
		memset(&prev[0], 0xFF, prev.size() * sizeof(prev[0]));
		memset(&realDist[0], 0x3F, realDist.size() * sizeof(realDist[0]));
		memset(&adjustedDist[0], 0x3F, adjustedDist.size() * sizeof(adjustedDist[0]));
		memset(&visited[0], 0, visited.size());
		adjustedDist[source] = realDist[source] = 0;
		priority_queue< pair<int, int> > Q;
		Q.push(make_pair(0, source));
		while (!Q.empty()) {
			int t = Q.top().second;
			Q.pop();
			if (visited[t])
				continue;
			visited[t] = 1;
			for (auto i : ngh[t])
			if (C[t][i] > F[t][i]) {
				int newAdjustedDistance = adjustedDist[t] + W[t][i] + oldDist[t] - oldDist[i];
				assert(W[t][i] + oldDist[t] - oldDist[i] >= 0);
				if (newAdjustedDistance < adjustedDist[i]) {
					Q.push(make_pair(-newAdjustedDistance, i));
					adjustedDist[i] = newAdjustedDistance;
					realDist[i] = realDist[t] + W[t][i];
					prev[i] = t;
				}
			}
		}
	}
	int FordFulkerson() {
		int N = ngh.size();
		vector<int> oldist(N);
		BellmanFord(oldist);

		vector<int> dist(N);
		vector<int> prev(N);
		vector<int> realDist(N);
		vector<char> visited(N);
		int totalCost = 0;
		while (true) {
			Dijkstra(dist, oldist, realDist, visited, prev);
			if (prev[sink] == -1)
				break;
			int minToSend = 0x3F3F3F3F;
			int curNod = sink;
			while (prev[curNod] != -1) {
				if (C[prev[curNod]][curNod] - F[prev[curNod]][curNod] < minToSend)
					minToSend = C[prev[curNod]][curNod] - F[prev[curNod]][curNod];
				curNod = prev[curNod];
			}
			curNod = sink;
			while (prev[curNod] != -1) {
				F[prev[curNod]][curNod] += minToSend;
				F[curNod][prev[curNod]] -= minToSend;
				curNod = prev[curNod];
			}
			totalCost += minToSend * realDist[sink];
			memcpy(&oldist[0], &realDist[0], oldist.size() * sizeof(oldist[0]));
		}
		return totalCost;
	}
};

int main() {
	assert(freopen(InFile, "r", stdin));
	assert(freopen(OuFile, "w", stdout));
	int N, M, S, D;
	readNum(N); readNum(M); readNum(S); readNum(D);
	graph G(N, S - 1, D - 1);
	while (M--) {
		int a, b, c, w;
		readNum(a); readNum(b); readNum(c); readNum(w);
		G.insertEdge(a - 1, b - 1, c, w);
	}
	printf("%d\n", G.FordFulkerson());
	return 0;
}