Cod sursa(job #442131)

Utilizator MciprianMMciprianM MciprianM Data 13 aprilie 2010 21:53:20
Problema Flux maxim de cost minim Scor 0
Compilator cpp Status done
Runda Arhiva educationala Marime 4.64 kb
# include <fstream>
# include <iostream>
# include <vector>
# include <queue>

using namespace std;

const int MAXN = 512, inf = 2000000001;
int maxFlow, minCost;
int N, M, S, D, pqSize;
int cap [ MAXN ] [ MAXN ], cost [ MAXN ] [ MAXN ];
int dist [ MAXN ], from [ MAXN ], pq [ MAXN ], poz [ MAXN ];
bool viz [ MAXN ], popped [ MAXN ];
vector <int> G [ MAXN ];
queue <int> q;

void interch ( int &a, int &b ){
	
	int aux;
	
	aux = a;
	a = b;
	b = aux;
	
}

void BellmanFord (){

	int i;
	vector <int> :: iterator it;
	
	for ( i = 1; i <= N; ++ i )
		dist [ i ] = inf;
	dist [ S ] = 0;
	
	q . push ( S );
	while ( ! q. empty () ){
		for ( it = G [ q . front () ] . begin (); it != G [ q . front () ] . end (); ++ it )
			if ( cap [ q . front () ] [ * it ] > 0 && dist [ q . front () ] != inf
				&& dist [ * it ] > dist [ q . front () ] + cost [ q . front () ] [ * it ] ){
					dist [ * it ] = dist [ q . front () ] + cost [ q . front () ] [ * it ];
					q . push ( * it );
			}
		q . pop ();
	}
}

void graphTransform (){
	
	int i;
	vector <int> :: iterator it;
	
	for ( i = 1; i <= N; ++ i )
		for ( it = G [ i ] . begin (); it != G [ i ] . end (); ++ it )
			cost [ i ] [ * it ] += dist [ i ] - dist [ * it ];
	
}

void pqInsert ( int x ){
	
	int p;
	
	pq [ p = ++ pqSize ] = x;
	while ( p != 1 && dist [ pq [ p ] ] < dist [ pq [ p / 2 ] ] ){
		interch ( pq [ p ], pq [ p / 2 ] );
		poz [ pq [ p ] ] = p;
		p = p / 2;
	}
	poz [ x ] = p;
	
}

bool pqEmpty (){
	
	return ( pqSize == 0 );
	
}

int pqMin (){
	
	return pq [ 1 ];
	
}

void pqUpdate ( int x ){

	// key [ x ] only decreases
	
	int p = poz [ x ];
	
	while ( p != 1 && dist [ pq [ p ] ] < dist [ pq [ p / 2 ] ] ){
		interch ( pq [ p ], pq [ p / 2 ] );
		poz [ pq [ p ] ] = p;
	}
	poz [ x ] = p;
	
}

void heapify ( int po ){
	
	int minv, p;
	
	p = po;
	minv = dist [ pq [ po ] ];
	
	if ( 2 * po <= pqSize && dist [ 2 * po ] < minv ){
		p = po * 2;
		minv = dist [ 2 * po ];
	}
	
	if ( 2 * po + 1 <= pqSize && dist [ 2 * po + 1 ] < minv ){
		p = po * 2;
		minv = dist [ 2 * po + 1 ];
	}
	
	if ( p != po ){
		
		interch ( pq [ p ], pq [ po ] );
		poz [ pq [ p ] ] = p;
		poz [ pq [ po ] ] = po;
		heapify ( p );
		
	}
	
}

void pqPop(){
	
	interch ( pq [ 1 ], pq [ pqSize ] );
	poz [ pq [ 1 ] ] = 1;
	poz [ pq [ pqSize ] ] = pqSize;
	-- pqSize;
	heapify ( 1 );
}

void oneSourceMultipleDestinationsMinPaths (){
	
	// Dijkstra
	
	int i, x;
	vector <int> :: iterator it;
	
	memset ( viz, 0, sizeof ( viz ) );
	memset ( from, -1, sizeof ( from ) );
	memset ( popped, 0, sizeof ( popped ) );
	for ( i = 1; i <= N; ++ i )
		dist [ i ] = inf;
	dist [ S ] = 0;
	
	pqInsert ( S );
	while ( ! pqEmpty () ){
		x = pqMin ();
		popped [ x ] = true;
		for ( it = G [ x ] . begin (); it != G [ x ] . end (); ++ it )
			if ( cap [ x ] [ * it ] > 0 && dist [ * it ] > dist [ x ] + cost [ x ] [ * it ] ){
				dist [ * it ] = dist [ x ] + cost [ x ] [ * it ];
				from [ * it ] = x;
				if ( ! viz [ * it ] )
					pqInsert ( * it );
				else if ( ! popped [ * it ] )
						pqUpdate ( * it );
				viz [ * it ] = true;
			}
		pqPop ();
	}
	
}

void findAugmentingPathOfMinCost ( int &flow, int &cst ){
	
	int dad;
	
	flow = inf; cst = 0;
	
	oneSourceMultipleDestinationsMinPaths ();
	
	if ( from [ D ] == -1 ){
		flow = 0;
		return;
	}
	
	dad = D;
	while ( from [ dad ] != -1 ){
		
		cst += cost [ from [ dad ] ] [ dad ];
		if ( cap [ from [ dad ] ] [ dad ] < flow )
			flow = cap [ from [ dad ] ] [ dad ];
		dad = from [ dad ];
		
	}
	
	dad = D;
	while ( from [ dad ] != -1 ){
		
		cap [ dad ] [ from [ dad ] ] += flow;
		cap [ from [ dad ] ] [ dad ] -= flow;
		dad = from [ dad ];
		
	}
	
}

void fmcm (){
	
	int flux, cst;
	
	BellmanFord ();
	
	do{
		// make graph costs nonnegative
		graphTransform ();
		findAugmentingPathOfMinCost ( flux, cst );
		maxFlow += flux;
		minCost += flux * cst;
		
	}	while ( flux > 0 );
	
}

void creareGraf (){
	
	/* Graful contine cel mult un arc intre oricare doua noduri x si y,
		iar daca ( x, y ) apartine lui E, atunci ( y, x ) nu apartine lui E,
		unde E este multimea arcelor	*/
	
	int i, x, y;
	ifstream f ( "fmcm.in" );
	
	f >> N >> M >> S >> D;
	for ( i = 0; i < M; ++ i ){
		f >> x >> y;
		f >> cap [ x ] [ y ] >> cost [ x ] [ y ];
		cost [ y ] [ x ] = - cost [ x ] [ y ];
		G [ x ] . push_back ( y );
		G [ y ] . push_back ( x );
	}
	
	f . close ();
	
}

void afis (){
	
	ofstream g ( "fmcm.out" );
	g << minCost << '\n';
	g . close ();
	
}

int main(){
	
	creareGraf ();
	fmcm ();
	afis ();
	
	return 0;
	
}