Cod sursa(job #552915)

Utilizator feelshiftFeelshift feelshift Data 13 martie 2011 10:24:19
Problema Flux maxim de cost minim Scor 70
Compilator cpp Status done
Runda Arhiva educationala Marime 2.73 kb
// http://infoarena.ro/problema/fmcm
#include <fstream>
#include <vector>
#include <queue>
using namespace std;

#define maxSize 351
#define INFINITY 0x3f3f3f3f

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

int nodes,edges,source,destination;
int maxFlowMinCost;
bool visit[maxSize];
int dist[maxSize];
int father[maxSize];
int capacity[maxSize][maxSize];
int cost[maxSize][maxSize];
int currentFlow[maxSize][maxSize];
vector<int> graph[maxSize];

bool bellmanFord();

int main() {
	in >> nodes >> edges;
	in >> source >> destination;

	int from,to,flow,currentCost;
	for(int i=1;i<=edges;i++) {
		in >> from >> to >> flow >> currentCost;

		capacity[from][to] = flow;
		cost[from][to] = currentCost;
		cost[to][from] = -currentCost;

		graph[from].push_back(to);
		graph[to].push_back(from);
	}

	// cat timp gasim drumuri de ameliorare
	while(bellmanFord()) {
		int node;
		int minFlow = INFINITY;

		// parcurgem invers drumul cu cost minim de la destinatie la sursa
		for(node=destination;node!=source;node=father[node])
			// calculam valoaream minima cu care putem mari
			// fluxul pe acest drum, aceasta fiind valoarea
			// minima cu care poate fi marit fluxul asociat
			// fiecarei muchii care se afla pe drumul gasit
			minFlow = min(minFlow,capacity[father[node]][node] - currentFlow[father[node]][node]);

		if(minFlow) {
			for(node=destination;node!=source;node=father[node]) {
				currentFlow[father[node]][node] += minFlow;
				currentFlow[node][father[node]] -= minFlow;
			}

			maxFlowMinCost += minFlow * dist[destination];
		}
	}

	out << maxFlowMinCost << "\n";

	in.close();
	out.close();

	return (0);
}

bool bellmanFord() {
	memset(dist,INFINITY,sizeof(dist));
	dist[source] = 0;

	memset(visit,false,sizeof(visit));
	visit[source] = true;
	
	int node;
	vector<int>::iterator it,end;

	queue<int> myQueue;
	myQueue.push(source);

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

		end = graph[node].end();
		for(it=graph[node].begin();it!=end;++it)
			// daca fluxul asociat pana in acest moment
			// este strict mai mic decat capacitatea
			// muchiei iar distanta (costul) este mai mica
			if(capacity[node][*it] - currentFlow[node][*it] > 0 && dist[node] + cost[node][*it] < dist[*it]) {
				dist[*it] = dist[node] + cost[node][*it];	// actualizam distanta
				father[*it] = node;	// retinem tatal (pentru reconstructia drumului)

				if(!visit[*it]) {	// daca nu a fost vizitat
					myQueue.push(*it);	// il introducem in coada
					visit[*it] = true;	// il marcam ca vizitat
				}
			}

		visit[node] = false;
	}

	// daca s-a gasit drum de ameliorare
	if(dist[destination] != INFINITY)
		return true;
	else
		return false;
}