Cod sursa(job #703776)

Utilizator balakraz94abcd efgh balakraz94 Data 2 martie 2012 14:21:25
Problema Flux maxim de cost minim Scor 70
Compilator cpp Status done
Runda Arhiva educationala Marime 2.96 kb
#include<cstdio>
#include<vector>
#include<queue>
#include<bitset>
#include<algorithm>
#define infile "fmcm.in"
#define outfile "fmcm.out"
#define n_max 355
#define INF 1<<30
#define nxt *it
#define pii pair<int, int>
#define mkp make_pair
#define pb push_back
#define mkp make_pair
#define FOR(g) \
   for(vector<int> ::iterator it = g.begin(); it!=g.end(); ++it)
using namespace std;


vector <int> v[n_max];

int H[n_max], Poz[n_max];
int NH;

int Cost[n_max][n_max], C[n_max][n_max], F[n_max][n_max];

int Dist[n_max], T[n_max];

int Src, Sink, Sum;

int N, M;

long long MaxFlow;


void citeste()
{
	freopen(infile,"r",stdin);
	
	scanf("%d %d %d %d", &N, &M, &Src, &Sink);
	
	int x, y, cap, cost;
	
	while(M--)
	{
		scanf("%d %d %d %d", &x, &y, &cap, &cost);
		
		v[x].pb(y);
		v[y].pb(x);
		
		C[x][y] = cap;
		Cost[x][y] = cost;
		Cost[y][x] = -cost;
	}
	
	fclose(stdin);
}


void BellmanFord()
{
	queue < int > q;
	
	bitset < n_max > uz;
	
	for(int i=1; i<=N; ++i)
		Dist[i] = INF;
	
	q.push(Src);
	Dist[Src] = 0;
	
	while(!q.empty())
	{
		int x = q.front();
		q.pop();
		
		FOR(v[x])
			if(C[x][nxt] > F[x][nxt] && Dist[x] + Cost[x][nxt] < Dist[nxt]){
				
				Dist[nxt] = Dist[x] + Cost[x][nxt];
				
				if(uz[nxt])
					continue;
				
				q.push(nxt);
				uz[nxt] = 1;
			}
		uz[x] = 0;
	}	
	
	Sum = Dist[Sink];	
}



inline void pop()
{
	H[1] = H[NH--];
	Poz[H[1]] = 1;
	
	int ls, rs, son, k = 1;
	
	while(true)
	{
		son = k;
		ls = 2 * k;
		rs = 2 * k + 1;
		
		if(ls <= NH && Dist[H[ls]] < Dist[H[son]])
			son = ls;
		if(rs <= NH && Dist[H[rs]] < Dist[H[son]])
			son = rs;
		
		if(son == k)
			return;
		
		swap(Poz[H[k]], Poz[H[son]]);
		swap(H[k], H[son]);
		
		k = son;
	}
}


inline void push(int x)
{
	if(!Poz[x]){
		H[++NH] = x;
	    Poz[x] = NH;
	}
	
	int k = Poz[x];
	
	while(k>1 && Dist[H[k]] < Dist[H[k/2]])
	{
		swap(Poz[H[k]], Poz[H[k/2]]);
		swap(H[k], H[k/2]);
		
		k = k/2;
	}
}



int Dijkstra()
{
	for(int x=1; x<=N; ++x)
		FOR(v[x])
			if(Dist[x] != INF && Dist[nxt] != INF)
				Cost[x][nxt] += Dist[x] - Dist[nxt];
			
	for(int i=1; i<=N; ++i){
		Dist[i] = INF;
		T[i] = Poz[i] = 0;
	}
	
	Dist[Src] = 0;
	T[Src] = -1;
	
	NH = 0;
	push(Src);
	
	while(NH)
	{
		int x = H[1];
		pop();
		
		FOR(v[x])
			if(C[x][nxt] > F[x][nxt] && Dist[x] + Cost[x][nxt] < Dist[nxt])
			{
				Dist[nxt] = Dist[x] + Cost[x][nxt];
				
				T[nxt] = x;
				
				push(nxt);
			}
	}
	
	return T[Sink] != 0;
}



void rezolva()
{
	BellmanFord();
	
	while(Dijkstra())
	{
		int flow = INF;
		
		for(int i = Sink; i != Src; i = T[i])
			flow = min(flow, C[T[i]][i] - F[T[i]][i]);
		
		for(int i = Sink; i != Src; i = T[i]){
			F[T[i]][i] += flow;
			F[i][T[i]] -= flow;
		}
		Sum += Dist[Sink];
		
		MaxFlow += flow * Sum;
	}
}


void afiseaza()
{
	freopen(outfile,"w",stdout);
	
	printf("%lld\n", MaxFlow);
	
	fclose(stdout);
}


int main()
{
	citeste();
	
	rezolva();
	
	afiseaza();
	
	return 0;
}