Cod sursa(job #1600760)

Utilizator TeodorCotetCotet Teodor TeodorCotet Data 15 februarie 2016 13:08:43
Problema Flux maxim Scor 0
Compilator cpp Status done
Runda Arhiva educationala Marime 2.79 kb
#include <fstream>
#include <iostream>
#include <vector>
#include <queue>
#include <bitset>

using namespace std;

ifstream fin("fmcm.in");
ofstream fout("fmcm.out");

const int NMAX = 350;
const int MMAX = 12500;
const int INF = 0x1fffffff;

int n; int m; int source; int dest;

int cap[NMAX + 1][NMAX + 1];
int flow[NMAX + 1][NMAX + 1];
int cost[NMAX + 1][NMAX + 1];
/* res graph = cost - flow */

vector< vector<int> > g(NMAX + 1, vector<int>(0));

int before[NMAX + 1]; 

int minCost;

void read() {

	fin >> n >> m >> source >> dest;

	for(int i = 1; i <= m; ++i) {
		int x; int y; int capacity; int c;
		fin >> x >> y >> capacity >> c;

		cap[x][y] = capacity;
		cost[x][y] = c;
		cost[y][x] = -c;

		g[x].push_back(y);
		g[y].push_back(x);
	}
}

bool bellmanFord(int sursa, int dest, vector< vector<int> >& g) {

	queue<int> q;
	bitset<NMAX + 1> inQueue;
	vector<int> dist(NMAX + 1, INF);
	vector<int> cntQueue(NMAX + 1, 0);
	bool isReachable = false;

	q.push(sursa);
	inQueue[sursa] = true;
	dist[sursa] = 0;
	before[sursa] = sursa;
	cntQueue[sursa]++;

	while(q.empty() == false) {

		int node = q.front();
		q.pop();

		inQueue[node] = false;

		for(int x : g[node]) {

			int maxFlow = cap[node][x] - flow[node][x];
			
			/* Nu ne intereseaza decat sa gasim un drum care poate fi ameliorat dpdv al fluxului, dar sa fie
			minim dpdv al costului. Prima data cand se intalneste un flow > 0 si dist[x] = INF adica mai mare ca dist[node] + cost
			Daca exista un drum de ameliorare pentru flux de la sursa la destinatie, 
			nu va fi impedicata gasirea lui de conditia dist[node] + cost < dist[x]*/

			if(maxFlow > 0 && dist[node] + cost[node][x] < dist[x]) {

				before[x] = node;
				dist[x] = dist[node] + cost[node][x];

				if(cntQueue[x] == n) {
					cout << "Ciclu negativ" << '\n';
					return false;
				}

				if(inQueue[x] == false) {
					q.push(x);
					inQueue[x] = true;
					cntQueue[x]++;
				}

				if(x == dest) isReachable = true;
					
				

			}
		}
	}

	return isReachable;
}

void solve(int start, int dest, vector< vector<int> >& g) {

	/* La fiecare pas gasim un drum de la sursa la destinatie, unde se mai poate creste fluxul */
	/* Singura diferenta este ca acum vom lua acest drum ca fiind cel de cost minim */

	while(bellmanFord(start, dest, g)) {


		int x = dest; int maxFlow = INF;

		while(before[x] != x) {
			maxFlow = min(maxFlow, cap[before[x]][x] - flow[before[x]][x]);
			x = before[x];
		}

		x = dest;

		while(before[x] != x) {

			flow[before[x]][x] += maxFlow;
			flow[x][before[x]] -= maxFlow;
			minCost += maxFlow * cost[before[x]][x];
			x = before[x];
		}
	}
}

int main() {
	
	read();

	solve(source, dest, g);

	fout << minCost << '\n'; 

	return 0;
}