Cod sursa(job #1966013)

Utilizator SolcanMihaiSolcan Mihai Andrei SolcanMihai Data 14 aprilie 2017 20:19:30
Problema Flux maxim de cost minim Scor 50
Compilator cpp Status done
Runda Arhiva educationala Marime 2.7 kb
#include <cstdio>
#include <vector>
#include <queue>
#include <algorithm>

using namespace std;

const long long N = 360;
const long long inf = (1 << 27);

long long n, m, s, d;
long long flux[N][N];
long long capacitate[N][N];
long long cost[N][N];
long long oldDist[N];
long long dist[N];
vector<long long> vecini[N];
long long sol = 0;
long long solx = 0;
long long tata[N];

void citire()
{
	scanf("%lld %lld %lld %lld", &n, &m, &s, &d);
	s--;
	d--;
		
	long long tmp1, tmp2, tmp3, tmp4;

	for(long long i = 0; i < m; i++)
	{
		scanf("%lld %lld %lld %lld", &tmp1, &tmp2, &tmp3, &tmp4);

		tmp1--;
		tmp2--;

		vecini[tmp1].push_back(tmp2);
		vecini[tmp2].push_back(tmp1);
		capacitate[tmp1][tmp2] = tmp3;
		cost[tmp1][tmp2] = tmp4;
		cost[tmp2][tmp1] = -tmp4;
	}
}

void bellmanFord()
{
	for(long long i = 0; i < n; i++)
	{
		oldDist[i] = inf;
	}

	queue<long long> Q;

	Q.push(s);
	oldDist[s] = 0;

	while(Q.empty() == false)
	{
		long long x = Q.front();
		long long l = vecini[x].size();

		Q.pop();

		for(long long i = 0; i < l; i++)
		{
			if(oldDist[vecini[x][i]] > oldDist[x] + cost[x][vecini[x][i]] && flux[x][vecini[x][i]] < capacitate[x][vecini[x][i]])	
			{
				oldDist[vecini[x][i]] = oldDist[x] + cost[x][vecini[x][i]];
				Q.push(vecini[x][i]);
			}
		}
	}
}

bool dijkstra()
{
	for(long long i = 0; i < n; i++)
	{
		dist[i] = inf;
	}

	priority_queue<pair<long long, long long> > Q;	

	Q.push(make_pair(0, s));
	tata[s] = s;
	dist[s] = 0;

	while(Q.empty() == false)
	{
		long long x = Q.top().second;
		long long y = Q.top().first;

		Q.pop();

		if(dist[x] != y)
		{
			continue;
		}

		long long l = vecini[x].size();

		for(long long i = 0; i < l; i++)
		{
			if(flux[x][vecini[x][i]] < capacitate[x][vecini[x][i]])				
			{
				long long z = cost[x][vecini[x][i]] + oldDist[x] - oldDist[vecini[x][i]];

				if(flux[x][vecini[x][i]] < capacitate[x][vecini[x][i]] && dist[vecini[x][i]] > dist[x] + z)
				{
					dist[vecini[x][i]] = dist[x] + z;
					tata[vecini[x][i]] = x;
					Q.push(make_pair(dist[vecini[x][i]], vecini[x][i]));
				}
			}
		}
	}

	if(dist[d] != inf)
	{
		return true;
	}

	return false;
}

void solve()
{
	while(dijkstra() == true)
	{
		long long x = d;
		tata[s] = s;
		long long valMin = inf;

		while(x != tata[x])
		{
			valMin = min(valMin, capacitate[tata[x]][x] - flux[tata[x]][x]);
			x = tata[x];
		}
		
		x = d;

		if(valMin == 0)
		{
			return;
		}

		while(x != tata[x])
		{
			flux[tata[x]][x] += valMin;
			flux[x][tata[x]] -= valMin;
			solx += cost[tata[x]][x] * valMin;
			x = tata[x];
		}

		sol += valMin;
	}
}

void afisare()
{
	printf("%lld", solx);
}

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

	citire();
	bellmanFord();
	solve();
	afisare();

	return 0;
}