Cod sursa(job #938961)

Utilizator veleanduAlex Velea veleandu Data 14 aprilie 2013 17:09:36
Problema Algola Scor 50
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.86 kb
#include <cassert>
#include <cstdio>
#include <vector>
#include <queue>
#include <iostream>
using namespace std;

const int max_n=64, max_m=305, max_t=110, INF=0x3f3f3f3f;
const int Source=0, Sink=10000;

#define FORIT( it,v ) for( typeof((v).begin()) it=(v).begin(); it!=(v).end(); ++it )

struct edge{
	int a, b, c, f;
 /*   edge(){
		a = b = c = f = 0;
	}
	edge( int _a, int _b, int _c ){
		a = _a;
		b = _b;
		c = _c;
		f = 0;
	}*/
	int other( int nod ){
		return a+b-nod;
	}
	int cap( int nod ){
		if( nod == a )
			return c-f;
		return f;
	}
	void update( int nod, int p ){
		if( nod == a )
			f+=p;
		else
			f-=p;
	}
} StartEdge[max_m], empty;
vector<edge> Edge;

int n, m, i;
int Start[max_n], Target;
int a, b, L;
int t;

int From[Sink+5], MaxFlow;
vector<int> Vertex[Sink+5];
queue<int> Deq;

void make_empty();

bool Find_Flow(){
	make_empty();
	int nod, other;
	Deq.push( Source );
 	From[Source] = 1;
 	while( !Deq.empty() ){
		if( From[Sink] )
			break;
		nod = Deq.front();
		Deq.pop();
		FORIT( it, Vertex[nod] ){
			other = Edge[*it].other(nod);
 			if( Edge[*it].cap( nod ) && !From[other] ){
				From[other] = *it;
				Deq.push( other );
			}
		}
	}
	if( From[Sink] )
		;
	else
		return false;
	int mn=INF;
	for( nod = Sink; nod != Source; nod = Edge[ From[nod] ].other( nod ) )
		mn = min( mn, Edge[ From[nod] ].cap( Edge[ From[nod] ].other(nod) ) );
	for( nod = Sink; nod != Source; nod = Edge[ From[nod] ].other( nod ) ){
		Edge[ From[nod] ].update( Edge[From[nod]].other(nod), mn );
	}
	MaxFlow += mn;
	return true;
}
void make_empty(){
	for( int i=0; i<=Sink; ++i )
		From[i]=0;
	while( !Deq.empty() )
		Deq.pop();
}

void add_edge( int a, int b, int c ){
	Vertex[a].push_back( Edge.size() );
	Vertex[b].push_back( Edge.size() );
	empty.a=a;
	empty.b=b;
	empty.c=c;
	empty.f=0;
	Edge.push_back( empty );
}

void make_vertex( int T ){
	int i, a, b;
	for( i=1; i<=m; ++i ){
		// a->b
 		a = T*64 + StartEdge[i].a;
		b = (T+1)*64 + StartEdge[i].b;
		add_edge( a, b, StartEdge[i].c );

  		a = T*64 + StartEdge[i].b;
		b = (T+1)*64 + StartEdge[i].a;
		add_edge( a, b, StartEdge[i].c );
	}
	// de la el la el cu cap infinit :)
	for( i=1; i<=n; ++i ){
		a = T*64 + i;
		b = (T+1)*64 + i;
		add_edge( a, b, INF );
	}
	
	a = (T+1)*64 + 1;
	b = Sink;
	add_edge( a, b, INF );
}

int main(){
	Edge.push_back( empty );
	freopen("algola.in","r",stdin);
	freopen("algola.out","w",stdout);
	scanf("%d %d", &n, &m );
 	for( i=1; i<=n; ++i ){
		scanf("%d", &Start[i] );
		Target += Start[i];
	}
	for( i=1; i<=n; ++i ){
		scanf("%d %d %d", &a, &b, &L );
		StartEdge[i].a=a;
		StartEdge[i].b=b;
		StartEdge[i].c=L;
		StartEdge[i].f=0;
	}
	// facem muchiile initiale
	for( i=1; i<=n; ++i ){
		add_edge( Source, i, Start[i] );
	}
	add_edge( 1, Sink, INF );
	for( t=0; ; ++t ){
		while( Find_Flow() )
			;
        if( MaxFlow >= Target ){
			printf("%d\n", t );
			return 0;
		}
    	make_vertex( t );
	}
 		
	return 0;
}