Cod sursa(job #1564076)

Utilizator TimitocArdelean Andrei Timotei Timitoc Data 8 ianuarie 2016 09:52:37
Problema Flux maxim de cost minim Scor 50
Compilator cpp Status done
Runda Arhiva educationala Marime 2.8 kb
#include <iostream>
#include <cstdio>
#include <vector>
#include <queue>
#include <cstring>
#define MAXN 400
#define inf 1000000000

using namespace std;

int cost[MAXN][MAXN], oldCost[MAXN][MAXN], capac[MAXN][MAXN], flow[MAXN][MAXN];
vector<int> graf[MAXN];
int n, m, s, d, sol;
int distMin[MAXN], tat[MAXN];

void citire()
{
	int x, y, c, z;
    scanf("%d %d %d %d", &n, &m, &s, &d);
    for (int i = 1; i <= m; i++) {
		scanf("%d %d %d %d", &x, &y, &c, &z);
		graf[x].push_back(y);
		graf[y].push_back(x);
		cost[x][y] = oldCost[x][y] = z;
		cost[y][x] = oldCost[y][x] = -z;
		capac[x][y] += c;
    }
}

queue<int> q;
int einq[MAXN], pasi[MAXN];
void bellman(int start)
{
	for (int i = 0; i <= n; i++)
		distMin[i] = inf;
    q.push(start);
    einq[start] = 1;
    distMin[start] = 0;
    while (!q.empty()) {
        int nod = q.front();
        q.pop();
        einq[nod] = 0;
        for (int i = 0, t = graf[nod].size(); i < t; i++) {
            int y = graf[nod][i];
            if (capac[nod][y] && distMin[y] > distMin[nod] + cost[nod][y]) {
				distMin[y] = distMin[nod] + cost[nod][y];
				if (!einq[y]) {
					q.push(y);
					pasi[y]++;
					einq[y] = 1;
					if (pasi[y] - n > 5)
						cerr << "ERROR NEGATIVE CICLE";
				}
            }
        }
    }
}


void prepare(int dist[MAXN])
{
    for (int i = 1; i <= n; i++)
	for (int j = 0, t = graf[i].size(); j < t; j++) {
		int y = graf[i][j];
		if (dist[i] == inf || dist[y] == inf) continue;
		cost[i][y] = oldCost[i][y] + dist[i] - dist[y];
	}
}

int best[MAXN], real[MAXN];
struct cmp
{
    bool operator()(int a, int b) { return best[a] > best[b]; }
};
priority_queue<int, vector<int>, cmp> pq;
int dijkstra()
{
	for (int i = 0; i <= n; i++)
		best[i] = inf;
	while (!q.empty()) q.pop();
    for (best[s] = 0, real[s] = 0, pq.push(s); !pq.empty(); ) {
        int nod = pq.top();
        pq.pop();
        if (nod == d)
			continue ;
		for (int i = 0, t = graf[nod].size(); i < t; i++) {
            int y = graf[nod][i];
            if (capac[nod][y]-flow[nod][y] && best[y] > best[nod] + cost[nod][y]) {
				tat[y] = nod;
				real[y] = real[nod] + oldCost[nod][y];
				best[y] = best[nod] + cost[nod][y];
				pq.push(y);
            }
		}
    }
    return best[d] != inf;
}

void solve()
{
    for (;dijkstra(); prepare(real)) {
		int mini = inf;
		for (int last = d; last != s; last = tat[last])
			mini = min(mini, capac[tat[last]][last]-flow[tat[last]][last]);
		if (!mini) {
			cerr << "This should not have happened";
			continue;
		}
		for (int last = d;  last != s; last = tat[last]) {
			flow[tat[last]][last] += mini;
			flow[last][tat[last]] -= mini;
		}
		sol += mini * real[d];
    }
}

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

    citire();
    bellman(s);
    prepare(distMin);
    solve();
    printf("%d", sol);

    return 0;
}