Cod sursa(job #2811282)

Utilizator Rares31100Popa Rares Rares31100 Data 1 decembrie 2021 19:05:19
Problema Flux maxim de cost minim Scor 50
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 6.23 kb
#include <bits/stdc++.h>
using namespace std;

template <class T> class MaxFlowMinCost
{
public:
	static int gfSize;
	static vector <int>* gf;
	static map <pair<int, int>, T> cap, flux, cost;
	static T rezultatFlux, rezultatCost;
private:
	static vector <int>* gft;
	static bool* beenThere;
	//bellman-ford
	static T* dist;
	//djikstra
	static int* tata, * tabelTata;
	static T* positiveDist, * newDist;
	static bool* viz;
	//drum
	static pair <int, int>* muchie;
	static int* tabel;

	static void bellman()
	{
		queue <int> q;
		bool* inQ = new bool[gfSize + 1]();
		fill(inQ + 1, inQ + 1 + gfSize, 0);
		fill(beenThere + 1, beenThere + 1 + gfSize, 0);

		q.push(1);
		inQ[1] = beenThere[1] = true;
		dist[1] = 0;

		while (!q.empty())
		{
			int nod = q.front();
			q.pop();
			inQ[nod] = 0;

			for (auto vec : gf[nod])
				if (!beenThere[vec] || dist[nod] + cost[{nod, vec}] < dist[vec])
				{
					beenThere[vec] = true;
					dist[vec] = dist[nod] + cost[{nod, vec}];
					if (!inQ[vec])
					{
						q.push(vec);
						inQ[vec] = 1;
					}
				}
		}
	}

	static bool djikstra()
	{
		priority_queue <pair<int, int>> pq;
		pq.push({ 0, 1 });
		positiveDist[1] = 0;
		fill(viz + 1, viz + 1 + gfSize, 0);
		fill(beenThere + 1, beenThere + 1 + gfSize, 0);
		beenThere[1] = true;

		while (!pq.empty())
		{
			int nod = pq.top().second;
			pq.pop();

			if (viz[nod] == 1)
				continue;
			viz[nod] = 1;

			for (auto vec : gf[nod])
			{
				int positiveArc = cost[{nod, vec}] + dist[nod] - dist[vec];

				if (cap[{nod, vec}] && (!beenThere[vec] || positiveDist[nod] + positiveArc < positiveDist[vec]))
				{
					beenThere[vec] = true;
					positiveDist[vec] = positiveDist[nod] + positiveArc;
					pq.push({ -positiveDist[vec], vec });
					newDist[vec] = newDist[nod] + cost[{nod, vec}];

					tata[vec] = nod;
					tabelTata[vec] = 1;
				}
			}

			for (auto vec : gft[nod])
			{
				int positiveArc = -cost[{vec, nod}] + dist[nod] - dist[vec];
				if (flux[{nod, vec}] && (!beenThere[vec] || positiveDist[nod] + positiveArc < positiveDist[vec]))
				{
					beenThere[vec] = true;
					positiveDist[vec] = positiveDist[nod] + positiveArc;
					pq.push({ -positiveDist[vec], vec });
					newDist[vec] = newDist[nod] - cost[{vec, nod}];

					tata[vec] = nod;
					tabelTata[vec] = 2;
				}
			}
		}

		for (int i = 1; i <= gfSize; i++)
			dist[i] = newDist[i];

		return beenThere[gfSize];
	}

	static void drum(const int& lung)
	{
		T minim, suma = 0;

		if (tabel[1] == 1)
			minim = cap[{muchie[1].first, muchie[1].second}];
		else
			minim = flux[{muchie[1].first, muchie[1].second}];

		for (int i = 2; i <= lung; i++)
			if (tabel[i] == 1)
				minim = min(minim, cap[{muchie[i].first, muchie[i].second}]);
			else
				minim = min(minim, flux[{muchie[i].first, muchie[i].second}]);

		for (int i = 1; i <= lung; i++)
			if (tabel[i] == 1)
			{
				suma += cost[{muchie[i].first, muchie[i].second}] * minim;
				cap[{muchie[i].first, muchie[i].second}] -= minim;
				flux[{muchie[i].second, muchie[i].first}] += minim;
			}
			else
			{
				suma += -cost[{muchie[i].second, muchie[i].first}] * minim;
				flux[{muchie[i].first, muchie[i].second}] -= minim;
				cap[{muchie[i].second, muchie[i].first}] += minim;
			}

		rezultatFlux += minim;
		rezultatCost += suma;
	}

	static void deleteAll()
	{
		delete[] gf;
		delete[] gft;
		delete[] viz;
		delete[] beenThere;
		delete[] dist;
		delete[] positiveDist;
		delete[] tata;
		delete[] tabelTata;
		delete[] newDist;
		delete[] tabel;
		delete[] muchie;
		cap.clear();
		flux.clear();
		cost.clear();
	}
	static void assignAll(const int& n)
	{
		gf = new vector <int>[n + 1]();
		gft = new vector <int>[n + 1]();
		beenThere = new bool[n + 1]();
		viz = new bool[n + 1]();
		dist = new T[n + 1]();
		positiveDist = new T[n + 1]();
		newDist = new T[n + 1]();
		tata = new int[n + 1]();
		tabelTata = new int[n + 1]();
		tabel = new int[n + 1]();
		muchie = new pair<int, int>[n + 1]();
		gfSize = n;
		rezultatFlux = 0;
		rezultatCost = 0;
	}
public:
	static void generate(const int& n, vector <tuple<int, T, T>> graf[])
	{
		deleteAll();
		assignAll(n);

		for (int i = 1; i <= n; i++)
			for (auto vec : graf[i])
			{
				gf[i].push_back(get<0>(vec));
				gft[get<0>(vec)].push_back(i);
				cap[{i, get<0>(vec)}] = get<1>(vec);
				cost[{i, get<0>(vec)}] = get<2>(vec);
			}

		bellman();

		while (djikstra())
		{
			int nod = gfSize, vf = 0;
			while (nod != 1)
			{
				muchie[++vf] = { tata[nod], nod };
				tabel[vf] = tabelTata[nod];
				nod = tata[nod];
			}

			drum(vf);
		}
	}
};
template <class T> int MaxFlowMinCost<T>::gfSize = 0;
template <class T> vector <int>* MaxFlowMinCost<T>::gf = NULL;
template <class T> vector <int>* MaxFlowMinCost<T>::gft = NULL;
template <class T> map <pair<int, int>, T> MaxFlowMinCost<T>::cap = {};
template <class T> map <pair<int, int>, T> MaxFlowMinCost<T>::flux = {};
template <class T> map <pair<int, int>, T> MaxFlowMinCost<T>::cost = {};
template <class T> T MaxFlowMinCost<T>::rezultatFlux = 0;
template <class T> T MaxFlowMinCost<T>::rezultatCost = 0;
template <class T> bool* MaxFlowMinCost<T>::viz = NULL;
template <class T> bool* MaxFlowMinCost<T>::beenThere = NULL;
template <class T> T* MaxFlowMinCost<T>::dist = NULL;
template <class T> T* MaxFlowMinCost<T>::positiveDist = NULL;
template <class T> T* MaxFlowMinCost<T>::newDist = NULL;
template <class T> int* MaxFlowMinCost<T>::tata = NULL;
template <class T> int* MaxFlowMinCost<T>::tabelTata = NULL;
template <class T> int* MaxFlowMinCost<T>::tabel = NULL;
template <class T> pair <int, int>* MaxFlowMinCost<T>::muchie = NULL;

int n, m, s, d;
vector <tuple<int, long long, long long>> gf[400];
ifstream fin("fmcm.in");
ofstream fout("fmcm.out");

int main()
{
	fin >> n >> m >> s >> d;
	s++; d++;

	for (int k = 1, i, j, cap, cost; k <= m; k++)
	{
		fin >> i >> j >> cap >> cost;
		i++; j++;
		gf[i].push_back(make_tuple(j, cap, cost));
	}

	gf[1].push_back(make_tuple(s, 1000000, 0));
	gf[d].push_back(make_tuple(n + 2, 1000000, 0));
	n += 2;

	MaxFlowMinCost<long long>::generate(n, gf);
	fout << MaxFlowMinCost<long long>::rezultatCost;
	return 0;
}