Cod sursa(job #3032133)

Utilizator CristeaCristianCristea Cristian CristeaCristian Data 21 martie 2023 14:48:27
Problema Flux maxim de cost minim Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.79 kb
#include <cmath>
#include <functional>
#include <fstream>
#include <iostream>
#include <vector>
#include <algorithm>
#include <string>
#include <set>
#include <map>
#include <list>
#include <time.h>
#include <math.h>
#include <random>
#include <deque>
#include <queue>
#include <unordered_map>
#include <unordered_set>
#include <iomanip>
#include <bitset>
#include <sstream>
#include <cassert>
#include <chrono>
#include <complex>
#include <cstring>
#include <numeric>

using namespace std;

struct MCMF
{
	const int INF = (int)1e9 + 7;

	struct Edge
	{
		int to, cap, cost;
	};
	int n;
	int s;
	int d;
	vector<Edge> edges;
	vector < vector<int>> g;
	vector<int> dist;
	vector<int> dist2;
	vector<bool> inq;
	vector<int> paredge;

	void init(int nn, int ss, int dd)
	{
		n = nn;
		s = ss;
		d = dd;
		s--;
		d--;
		assert(0 <= s && s < n);
		assert(0 <= d && d < n);
		edges.clear();
		dist.clear();
		dist2.clear();
		g.clear();
		inq.clear();
		paredge.clear();

		g.resize(n);
		dist.resize(n);
		inq.resize(n);
		paredge.resize(n);
		dist2.resize(n);
	}

	void addedge(int a, int b, int cap, int cost)
	{
		a--;
		b--;
		assert(0 <= a && a < n);
		assert(0 <= b && b < n);
		edges.push_back({ b, cap, cost });
		edges.push_back({ a, 0, -cost });
		g[a].push_back((int)edges.size() - 2);
		g[b].push_back((int)edges.size() - 1);
	}

	void bellman()
	{
		for (int i = 0; i < n; i++) dist[i] = INF, inq[i] = 0;
		queue<int> q;
		auto relax = [&](int v, int val, int specedge)
		{
			assert(0 <= v && v < (int)dist.size());
			assert(0 <= v && v < (int)inq.size());
			if (val < dist[v])
			{
				dist[v] = val;
				paredge[v] = specedge;
				if (!inq[v]) inq[v] = 1, q.push(v);
			}
		};
		relax(s, 0, -1);
		while (!q.empty())
		{
			int a = q.front();
			assert(inq[a]);
			inq[a] = 0;
			q.pop();
			for (auto& i : g[a])
			{
				if (edges[i].cap)
				{
					relax(edges[i].to, dist[a] + edges[i].cost, i);
				}
			}
		}
	}

	void spfa()
	{
		for (int i = 0; i < n; i++) dist2[i] = INF;
		priority_queue<pair<int, int>> q;
		auto relax = [&](int v, int val, int specedge)
		{
			assert(0 <= v && v < (int)dist.size());
			assert(0 <= v && v < (int)inq.size());
			if (val < dist2[v])
			{
				dist2[v] = val;
				paredge[v] = specedge;
				q.push({ -dist2[v], v });
			}
		};
		relax(s, 0, -1);
		while (!q.empty())
		{
			auto it = q.top();
			q.pop();
			int a =it.second;
			if (-it.first != dist2[a])
			{
				continue;
			}
			for (auto& i : g[a])
			{
				if (edges[i].cap)
				{
					relax(edges[i].to, dist2[a] + edges[i].cost + (dist[a] - dist[edges[i].to]), i);
				}
			}
		}
		for (int i = 0; i < n; i++)
		{
			dist[i] = dist2[i] + dist[i];
		}
	}


	pair<int, long long> solve()
	{
		int flow = 0;
		long long cost = 0;

		bellman();

		while (1)
		{
			spfa();
			if (dist2[d] == INF) break;
			int mn = INF, curv = d;
			while (curv != s)
			{
				mn = min(mn, edges[paredge[curv]].cap);
				curv = edges[paredge[curv] ^ 1].to;
			}
			assert(mn > 0);
			flow += mn;
			cost += mn * (long long)dist[d];
			curv = d;
			while (curv != s)
			{
				edges[paredge[curv]].cap -= mn;
				edges[paredge[curv]^1].cap += mn;
				curv = edges[paredge[curv] ^ 1].to;
			}
		}
		return { flow, cost };
	}
};

signed main()
{
#ifdef ONPC
	FILE* stream;
	freopen_s(&stream, "input.txt", "r", stdin);
#else
	ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
	freopen("fmcm.in", "r", stdin);
	freopen("fmcm.out", "w", stdout);
#endif

	int n, m, s, d;
	cin >> n >> m >> s >> d;

	MCMF f;
	f.init(n, s, d);

	for (int i = 0; i < m; i++)
	{
		int a, b, c, d;
		cin >> a >> b >> c >> d;
		f.addedge(a, b, c, d);
	}
	cout << f.solve().second << "\n";

	return 0;
}