Cod sursa(job #2884064)

Utilizator FunnyStockyMihnea Andreescu FunnyStocky Data 2 aprilie 2022 12:49:14
Problema Flux maxim de cost minim Scor 50
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 2.57 kb
#include <iostream>
#include <vector> 
#include <algorithm> 
#include <string> 
#include <cassert> 
#include <algorithm> 
#include <set> 
#include <iomanip> 
#include <queue> 
#include <deque> 
#include <unordered_set> 
#include <unordered_map> 
#include <functional> 
#include <cmath> 
#include <map> 
#include <random> 
#include <chrono> 
#include <cstdio> 

bool home = true;
using namespace std;

typedef long long ll;

const int FN = 350 + 7;
const int FM = 12500 + 7;
const int INF = (int)1e9 + 7;

struct Edge {
	int to;
	int cap;
	int cost;
};

int fn, fm, fs, fd;
Edge edges[2 * FM];
int inds[FN][FN], dim[FN];
int best[FN];
int parrent_edge[FN];
bool inq[FN];
queue<int> fq;

void setup(int n, int s, int d) {
	fn = n;
	fm = 0;
	fs = s;
	fd = d;

	for (int i = 0; i < fn; i++) {
		dim[i] = 0;
	}
}

void addEdge(int a, int b, int cap, int cost) {
	assert(1 <= a && a <= fn);
	assert(1 <= b && b <= fn);
	inds[a][dim[a]++] = fm;
	inds[b][dim[b]++] = fm + 1;
	edges[fm++] = { b, cap, cost };
	edges[fm++] = { a, 0, -cost };
}

void bellman() {
	assert(fq.empty());
	
	for (int i = 1; i <= fn; i++) best[i] = INF, inq[i] = 0;

	inq[fs] = 1;
	best[fs] = 0;
	fq.push(fs);

	while (!fq.empty()) {
		int a = fq.front();
		fq.pop();
		inq[a] = 0;
		for (int _ = 0; _ < dim[a]; _++) {
			int i = inds[a][_];
			if (edges[i].cap) {
				int b = edges[i].to, cost = edges[i].cost;
				if (best[a] + cost < best[b]) {
					best[b] = best[a] + cost;
					parrent_edge[b] = i;
					if (!inq[b]) inq[b] = 1, fq.push(b);
				}
			}
		}
	}
}

pair<ll, ll> get() {
	ll flow = 0, cost = 0;
	while (1) {
		bellman();
		if (best[fd] == INF) break;
		int mn = INF;

		int vertex = fd;
		while (vertex != fs) {
			int i = parrent_edge[vertex];
			assert(edges[i].to == vertex);

			mn = min(mn, edges[i].cap);

			vertex = edges[i ^ 1].to;
		}

		vertex = fd;

		while (vertex != fs) {
			int i = parrent_edge[vertex];
			assert(edges[i].to == vertex);

			edges[i].cap -= mn;
			edges[i ^ 1].cap += mn;
			
			vertex = edges[i ^ 1].to;
		}

		flow += mn;
		cost += mn * (ll)best[fd];
	}
	return { flow, cost };
}

signed main() {
	/*FILE* stream;
	freopen_s(&stream, "iron_man.txt", "r", stdin);*/
	freopen("fmcm.in", "r", stdin);
	freopen("fmcm.out", "w", stdout);
	int n, m, s, d;
	cin >> n >> m >> s >> d;
	setup(n, s, d);
	for (int i = 1; i <= m; i++) {
		int a, b, c, d;
		cin >> a >> b >> c >> d;
		addEdge(a, b, c, d);
	}
	auto fl = get();
	//cout << fl.first << "\n";
	cout << fl.second << "\n";
}