Cod sursa(job #777010)

Utilizator danalex97Dan H Alexandru danalex97 Data 10 august 2012 20:02:28
Problema Flux maxim Scor 40
Compilator cpp Status done
Runda Arhiva educationala Marime 2.56 kb
// Vom explica fluxul ca fiind o retea de trinsport ( sa zicem ceva tevi )
// Fiecare teava are o capacitate data , nepund sa curga mai multa apa prin
// teava respectiva. Tu trebuie sa intuiesti mersul apei. Pesupund ca apa curge 
// intr-un minut din punctul de start la cel tina , cata apa ajunge la final
// pe minut. 
// Ca si graf , se poate intui ca graful este unidirectional. Exemplu:
//
// Start -> A ( maxim 3 ) -> C( maxim 3 ) |
//  	 -> B ( maxim 1 ) |-> C( maxim 5 )| -> End ( maxim 2 )
//         	              |-> D( maxim 4 ) -> E( maxim 2 ) -> End ( maxim 3 )
//	REZULTAT : 3;
// 
// Consideram tevile ca fiind bidirectionale , capacitatile pundau-se modifica
// pe parcursul algoritmului. Initial arcele de forma y -> x au capacitate 0
// Daca trece o catitate de apa prin teava x -> y , atunci Cap[x][y]-=c.
// Daca capacitate intr-o parte scade , atunci capacitate opusa crest Cap[y][x]+=c
// Bazandu-ne pe aceasta observatie la fiecare pas vom contrui arborele BFS si ne
// vom opri doar cand nu se mai poate ajunge la punctul tinta prin BFS.
// La fiecare pas trimite flux de la Start la nodurile legate de End. 
// ( in exemplu C si E )
// Consecitele fiecarui pas sunt modifcarile arborelui BFS din cauza fluctuatiei 
// capacitatii muchiilor. 
// In final Complexitatea este O(N*M*M) amortizat

#include <fstream>
#include <vector>
using namespace std;

const int Nmax=1011;
const int Mmax=5011;
const int oo=0x3f3f3f3f;

int Cap[Nmax][Nmax];
int Dad[Nmax],Marked[Nmax];
vector<int> Leg[Nmax];
int N,M,Flux,Fmin;

ifstream F("maxflow.in");
ofstream G("maxflow.out");

void Get( int Nod )
{
	Marked[Nod]=1;
	if ( Nod==N ) return;
	
	for (int i=0; i < int(Leg[Nod].size()) ; ++i)
		if ( !Marked[Leg[Nod][i]] && Cap[Nod][Leg[Nod][i]] )
		{
			Dad[ Leg[Nod][i] ]=Nod;
			Get( Leg[Nod][i] );
		}
}

int BF()
{
	for (int i=1;i<=N;++i) Marked[i]=0;
	
	Get( 1 );
	
	return Marked[N];
}

int main()
{
	F>>N>>M;
	for (int i=1,x,y,z;i<=M;++i)
	{	
		F>>x>>y>>z;
		Cap[x][y]=z;
		Cap[y][x]=0;
		Leg[x].push_back( y );
		Leg[y].push_back( x );
	}
	
	while ( BF() )
		for (int i=0; i < int(Leg[N].size()) ; ++i)
		{
			int Nod=Leg[N][i];
			
			if ( Cap[Nod] == 0 || !Marked[Nod] ) continue;
			
			Dad[N]=Nod;
			Fmin=oo;
			
			for (int Act=N; Act!=1; Act=Dad[Act] ) 
				Fmin=min( Fmin, Cap[ Dad[Act] ][Act] );
			if ( Fmin == 0 ) continue;
			
			for (int Act = N; Act != 1; Act = Dad[Act])
			{
				Cap[ Dad[Act] ][Act] -= Fmin;
				Cap[Act][ Dad[Act] ] += Fmin;
			}
			
			Flux+=Fmin;
		}

	G<<Flux<<'\n';
}