Cod sursa(job #680391)

Utilizator balakraz94abcd efgh balakraz94 Data 15 februarie 2012 15:32:31
Problema Flux maxim de cost minim Scor 50
Compilator cpp Status done
Runda Arhiva educationala Marime 2.86 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 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 Cost[n_max][n_max], C[n_max][n_max], F[n_max][n_max], Dist[n_max], T[n_max];

int poz[n_max], H[n_max], NN;

int N, M, Src, Sink;

int Sum;



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



void BellmanFord()
{	
	for(int i=1;i<=N;++i)
		Dist[i] = INF;
	Dist[Src] = 0;
	
	int stop = 1;

	for(int i=1;i<=N && stop; ++i)
	{
		stop = 0;
		
		for(int nod=1; nod<=N; ++nod)
			FOR(v[nod])
				if(C[nod][nxt] > F[nod][nxt] && Dist[nod] + Cost[nod][nxt] < Dist[nxt]) 
				{
					stop = 1;
				
					Dist[nxt] = Dist[nod] + Cost[nod][nxt];
				}
	}

	Sum = Dist[Sink];
}



inline int pop()
{
	int nmin = H[1];
	poz[nmin] = 0;
	
	H[1] = H[NN--];
	poz[H[1]] = 1;
	
	int k = 1, ls, rs, son;
	
	while(1)
	{
		son = k;
		ls = k<<1;
		rs = k<<1 + 1;
		
		if(ls <= NN && Dist[H[ls]] < Dist[H[son]])
			son = ls;
		if(rs <= NN && Dist[H[rs]] < Dist[H[son]])
			son = rs;
		
		if(son == k)
			break;
		
		swap(poz[H[son]], poz[H[k]]);
		swap(H[son], H[k]);
		
		k = son;
	}
	
	return nmin;
}


inline void push(int x)
{
	int k;
	
	if(poz[x])
		k = poz[x];
	else
	{
		H[++NN] = x;
		poz[x] = NN;
		k = NN;
	}
	
	while(k > 1 && Dist[H[k]] < Dist[H[k>>1]])
	{
		swap(poz[H[k]], poz[H[k>>1]]);
		swap(H[k], H[k>>1]);
		
		k >>= 1;
	}
}



inline bool Dijkstra()
{
	for(int i=1; i<=N; i++)
		FOR(v[i])
			if(Dist[i]!=INF && Dist[nxt]!=INF)
				Cost[i][nxt] += Dist[i] - Dist[nxt];

	for(int i=1;i<=N;i++)
	{
		Dist[i] = INF;
		T[i] = poz[i] = 0;
	}		
	Dist[Src] = 0;
	
	push(Src);
	
	while(NN)
	{
		int nod = pop();

		FOR(v[nod])
			if(C[nod][nxt] - F[nod][nxt] > 0 && Dist[nod] + Cost[nod][nxt] < Dist[nxt])
			{
				Dist[nxt] = Dist[nod] + Cost[nod][nxt];
				push(nxt);
				T[nxt] = nod;
			}
	}
	
	return Dist[Sink] != INF ;
}



long long Flux()
{
	long long sol = 0;
	
	while(Dijkstra())
	{
		
		int fmin = INF;
	
		for(int i = Sink; i != Src; i = T[i])
			fmin = min(fmin, C[T[i]][i] - F[T[i]][i]);
	
		for(int i = Sink; i != Src; i = T[i])
		{
			F[T[i]][i] += fmin;
			F[i][T[i]] -= fmin;
		}
	
		Sum += Dist[Sink];
		
		sol += Sum * fmin;
	}
	
	return sol;
}



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


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