Cod sursa(job #342855)

Utilizator CezarMocanCezar Mocan CezarMocan Data 23 august 2009 22:19:38
Problema Flux maxim de cost minim Scor 20
Compilator cpp Status done
Runda Arhiva educationala Marime 3.61 kb
#include <cstdio>
#include <vector>
#include <cstring>
#define maxn 600
#define inf 0x3f

using namespace std;

int n, m, s, d;
int a, b, cap, ct, i, j;
vector <int> g[maxn], cost[maxn], tru[maxn];
int f[maxn][maxn], c[maxn][maxn];
int flux[maxn], up[maxn], viz[maxn];
int dist[maxn], dmin[maxn];
int heap[2 * maxn], heap_sz, poz_heap[maxn];
bool ok;
int rez, sum;

inline void bford(int src) {
	int p, u, i, nod, fiu;
	int q[maxn * maxn];

	dmin[src] = 0;
	q[1] = src;
	p = u = 1;
	memset(viz, 0, sizeof(viz));

	while (p <= u) {
		nod = q[p];
		viz[nod] = 0;

		for (i = 0; i < g[nod].size(); i++) if (tru[nod][i]) {
			fiu = g[nod][i];
			if (dmin[nod] + cost[nod][i] < dmin[fiu]) {
				dmin[fiu] = dmin[nod] + cost[nod][i];
				if (viz[fiu] == 0) {
					u++;
					q[u] = fiu;
					viz[fiu] = 1;
				}
			}
		}

		p++;
	}

	sum = dmin[d];
}

void init() {
	memset(flux, 0, sizeof(flux));
	memset(up, -1, sizeof(up));
	memset(dmin, inf, sizeof(dmin));
	dmin[s] = 0;
	ok = 0;
}

inline void swap(int &a, int &b) {
	int aux;
	aux = a; a = b; b = aux;
}

inline void heap_down() {
	int nod = 1;
	while (nod <= heap_sz) {
//		fprintf(stderr, "%d\n", nod);
		if (dmin[heap[nod]] > min(dmin[heap[2 * nod]], dmin[heap[2 * nod + 1]])) {
			if (dmin[heap[2 * nod]] < dmin[heap[2 * nod + 1]]) {
				swap(heap[nod], heap[2 * nod]);
				poz_heap[heap[nod]] = nod;
				poz_heap[heap[2 * nod]] = 2 * nod;
				nod = 2 * nod;
			}
			else {
				swap(heap[nod], heap[2 * nod + 1]);
				poz_heap[heap[nod]] = nod;
				poz_heap[heap[2 * nod + 1]] = 2 * nod + 1;
				nod = 2 * nod + 1;
			}
		}
		else
			break;
	}
}

inline void heap_up(int nod) {
	while (nod > 1) {
//		fprintf(stderr, "%d\n", nod);
		if (dmin[heap[nod]] < dmin[heap[nod / 2]]) {
			swap(heap[nod], heap[nod / 2]);
			poz_heap[heap[nod]] = nod;
			poz_heap[heap[nod / 2]] = nod / 2;
			nod /= 2;
		}
		else
			break;
	}
}

inline int dijkstra() {
	int i, j, fiu, nod, fmin;

	dmin[s] = 0;

	//mai intai ar trebui sa mesteresc la costuri
	for (i = 1; i <= n; i++) 
		for (j = 0; j < g[i].size(); j++) {
			fiu = g[i][j];
			if (dmin[i] <= 1000000000  && dmin[fiu] <= 1000000000) 
				cost[i][j] += dmin[i] - dmin[fiu];
		}

	init();

	//sa fac initializari pentru dijkstra
	heap_sz = 0;
	for (i = 1; i <= n; i++) {
		heap_sz++;
		heap[i] = i;
		poz_heap[i] = heap_sz;
	}

	swap(heap[1], heap[s]);
	poz_heap[1] = s; poz_heap[s] = 1;

	//dijkstra propriu-zis

	for (i = 1; i <= n; i++) {
		nod = heap[1];
//		fprintf(stderr, "%d %d\n", nod, dmin[nod]);

		for (j = 0; j < g[nod].size(); j++) {
			fiu = g[nod][j];
//			fprintf(stderr, "%d\n", fiu);
			if (f[nod][fiu] < c[nod][fiu] && dmin[nod] + cost[nod][j] < dmin[fiu]) {
				dmin[fiu] = dmin[nod] + cost[nod][j];
//				fprintf(stderr, "%d\n", poz_heap[fiu]);
				heap_up(poz_heap[fiu]);
				up[fiu] = nod;
			}
		}

		swap(heap[1], heap[heap_sz]);
		heap_down();
		heap_sz--;
	}

	if (dmin[d] > 1000000000)
		return 0;

	ok = 1;
	fmin = 1000000000;
	for (i = d; i != s; i = up[i])
		fmin = min(fmin, c[up[i]][i] - f[up[i]][i]);

	for (i = d; i != s; i = up[i]) {
		f[up[i]][i] += fmin;
		f[i][up[i]] -= fmin;
	}

	sum += dmin[d];
	return (sum * fmin);
	
}

int main() {
	freopen("fmcm.in", "r", stdin);
	freopen("fmcm.out", "w", stdout);

	scanf("%d%d%d%d", &n, &m, &s, &d);

	for (i = 1; i <= m; i++) {
		scanf("%d%d%d%d", &a, &b, &cap, &ct);
		g[a].push_back(b);
		tru[a].push_back(1);
		g[b].push_back(a);
		tru[b].push_back(0);
		c[a][b] = cap;
		cost[a].push_back(ct);
		cost[b].push_back(-ct);
	}

	memset(dmin, 0x3f, sizeof(dmin));
	dmin[0] = 1000000000;
	bford(s);

	ok = 1;
	while (ok) {
		rez += dijkstra();
//		fprintf(stderr, "%d\n", rez);
	}

	printf("%d\n", rez);

	return 0;
}