Cod sursa(job #719780)

Utilizator Addy.Adrian Draghici Addy. Data 22 martie 2012 01:58:25
Problema Flux maxim de cost minim Scor 70
Compilator cpp Status done
Runda Arhiva educationala Marime 3.27 kb
#include <cstdio>
#include <cstring>
#include <vector>
#include <queue>

using namespace std;

#define NMAX 355
#define INF 0x3f3f3f3f

#define fiu (it -> first)
#define cst (it -> second)

bool viz[NMAX];
int C[NMAX][NMAX], F[NMAX][NMAX], T[NMAX], H[NMAX], D[NMAX], poz[NMAX], N, M, K, S, DEST;
vector < pair <int, int> > G[NMAX];
queue <int> Q;

bool dijkstra ();
void up_heap (int), down_heap (int), insert_heap (int), delete_heap (int), update_costs (), bellman_ford (), input (), output ();
long long fmcm ();

int main () {
	
	input ();
	
	output ();
	
	return 0;
}

long long fmcm () {
	
	bellman_ford ();
	long long total = D[DEST];
	
	long long sol = 0; int nod, minim;
	while (dijkstra ()) {
		
		minim = INF;
		for (nod = DEST; nod != S; nod = T[nod])
			minim = min (minim, C[ T[nod] ][nod] - F[ T[nod] ][nod]);
		
		for (nod = DEST; nod != S; nod = T[nod]) {
			F[ T[nod] ][nod] += minim;
			F[nod][ T[nod] ] -= minim;
		}
		
		total += D[DEST];
		sol += 1LL * minim * total;
	}
	
	return sol;
}

bool dijkstra () {
	
	int nod;
	vector < pair <int, int> >::iterator it;
	
	update_costs ();
	
	memset (poz, 0, sizeof (poz));
	memset (D, INF, sizeof (D));
	
	D[S] = 0; insert_heap (S);
	while (K) {
		nod = H[1]; 
		delete_heap (1);
		
		for (it = G[nod].begin (); it != G[nod].end (); it++)
			if (C[nod][fiu] > F[nod][fiu] && D[nod] + cst < D[fiu]) {
				D[fiu] = D[nod] + cst;
				T[fiu] = nod;
				
				if (!poz[fiu])
					insert_heap (fiu);
				else
					up_heap (poz[fiu]);
			}
	}
	
	if (D[DEST] != INF) return 1;
	return 0;
}

void update_costs () {
	
	for (int i = 1; i <= N; i++)
		for (vector < pair <int, int> >::iterator it = G[i].begin (); it != G[i].end (); it++)
			cst += D[i] - D[fiu];
}

void insert_heap (int nod) {
	
	K++;
	H[K] = nod; poz[nod] = K;
	
	up_heap (K);
}

void delete_heap (int k) {
	
	H[k] = H[K]; poz[ H[k] ] = k;
	K--;
	
	down_heap (k);
}

void up_heap (int k) {
	
	int c = k, t = c >> 1;
	while (t > 0 && D[ H[c] ] < D[ H[t] ]) {
		swap (H[t], H[c]);
		poz[ H[t] ] = t, poz[ H[c] ] = c;
		
		c = t, t = c >> 1;
	}
}

void down_heap (int k) {
	
	int t = k, c = t << 1;
	if (c < K && D[ H[c + 1] ] < D[ H[c] ]) c++;
	
	while (c <= K && D[ H[c] ] < D[ H[t] ]) {
		swap (H[c], H[t]);
		poz[ H[c] ] = c, poz[ H[t] ] = t;
		
		t = c, c = t << 1;
		if (c < K && D[ H[c + 1] ] < D[ H[c] ]) c++;
	}
}

void bellman_ford () {
	
	int nod;
	memset (D, INF, sizeof (D));
	
	Q.push (S); D[S] = 0; viz[S] = 1;
	while (!Q.empty ()) {
		nod = Q.front ();
		for (vector < pair <int, int> >::iterator it = G[nod].begin (); it != G[nod].end (); it++) {
			
			if (C[nod][fiu] > F[nod][fiu] && D[nod] + cst < D[fiu]) {
				T[fiu] = nod;
				D[fiu] = D[nod] + cst;
				
				if (!viz[fiu]) Q.push (fiu), viz[fiu] = 1;
			}
		}
		
		Q.pop (); viz[nod] = 0;
	}
}

void input () {
	
	freopen ("fmcm.in", "r", stdin);
	
	scanf ("%d %d %d %d", &N, &M, &S, &DEST);
	
	int i, x, y, z, c;
	for (i = 1; i <= M; i++) {
		scanf ("%d %d %d %d", &x, &y, &c, &z);
		G[x].push_back (make_pair (y, z));
		G[y].push_back (make_pair (x, -z));
		C[x][y] = c, C[y][x] = 0;
	}
}

void output () {
	
	freopen ("fmcm.out", "w", stdout);
	
	printf ("%lld\n", fmcm ());
}