Cod sursa(job #1410210)

Utilizator vladrochianVlad Rochian vladrochian Data 30 martie 2015 22:24:23
Problema Flux maxim de cost minim Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 2.31 kb
#include <fstream>
#include <vector>
#include <queue>
#include <cstring>
using namespace std;

const int kMaxN = 355;
const int kInf = 0x3f3f3f3f;

int N, M, S, D;
vector<pair<int, int>> G[kMaxN];
int cap[kMaxN][kMaxN];
int cost;

int old_dist[kMaxN], real_dist[kMaxN], positive_dist[kMaxN];
int padre[kMaxN];
bool in_q[kMaxN];
struct HeapNode {
	int node, cost;
	HeapNode(int n, int c) : node(n), cost(c) {}
	bool operator<(const HeapNode &other) const {
		return cost > other.cost;
	}
};

void Read() {
	ifstream fin("fmcm.in");
	fin >> N >> M >> S >> D;
	while (M--) {
		int x, y, c, z;
		fin >> x >> y >> c >> z;
		G[x].emplace_back(y, z);
		G[y].emplace_back(x, -z);
		cap[x][y] = c;
	}
}

void BellmanFord() {
	queue<int> q;
	memset(old_dist, kInf, sizeof old_dist);
	old_dist[S] = 0;
	q.push(S);
	in_q[S] = true;
	while (!q.empty()) {
		int node = q.front();
		q.pop();
		in_q[node] = false;
		for (auto it : G[node])
			if (cap[node][it.first] && old_dist[node] + it.second < old_dist[it.first]) {
				old_dist[it.first] = old_dist[node] + it.second;
				if (!in_q[it.first]) {
					q.push(it.first);
					in_q[it.first] = true;
				}
			}
	}
}

bool Dijkstra() {
	priority_queue<HeapNode> q;
	memset(positive_dist, kInf, sizeof positive_dist);
	real_dist[S] = 0;
	positive_dist[S] = 0;
	q.emplace(S, 0);
	while (!q.empty()) {
		int node = q.top().node;
		int cost = q.top().cost;
		q.pop();
		if (positive_dist[node] != cost)
			continue;
		for (auto it : G[node]) {
			int new_cost = positive_dist[node] + it.second + old_dist[node] - old_dist[it.first];
			if (cap[node][it.first] && new_cost < positive_dist[it.first]) {
				positive_dist[it.first] = new_cost;
				real_dist[it.first] = real_dist[node] + it.second;
				padre[it.first] = node;
				q.emplace(it.first, new_cost);
			}
		}
	}
	memcpy(old_dist, real_dist, sizeof real_dist);
	return positive_dist[D] < kInf;
}

void Solve() {
	BellmanFord();
	while (Dijkstra()) {
		int flow = kInf;
		for (int i = D; i != S; i = padre[i])
			flow = min(flow, cap[padre[i]][i]);
		for (int i = D; i != S; i = padre[i]) {
			cap[padre[i]][i] -= flow;
			cap[i][padre[i]] += flow;
		}
		cost += flow * real_dist[D];
	}
}

int main() {
	Read();
	Solve();
	ofstream("fmcm.out") << cost << "\n";
	return 0;
}