Cod sursa(job #1659693)

Utilizator vladttturcuman vlad vladtt Data 22 martie 2016 14:47:10
Problema Flux maxim de cost minim Scor 70
Compilator cpp Status done
Runda Arhiva educationala Marime 3.09 kb
// Minimum Cost Maximum Flow.cpp : Defines the entry point for the console application.
//

//#include "stdafx.h"
#include <fstream>
#include <iostream>
#include <cstring>
#include <vector>
#include <queue>

#define NMax 600
using namespace std;
ifstream fin("fmcm.in");
ofstream fout("fmcm.out");

struct Pair {
	int n, c, ant;
	Pair(int _n, int _c, int _ant)
	{
		n = _n;
		c = _c;
		ant = _ant;
	}
	Pair() {}
};

vector<short int> v[NMax];

int n, m, s, d, i, a, b, c, z, S, MaxFlux = 1000000000;

int dist[NMax];

int maxx[NMax][NMax], cons[NMax][NMax], cost[NMax][NMax], _cost;
short int realCost[NMax][NMax];

Pair way[NMax];

void _read()
{
	fin >> n >> m >> s >> d;

	for (i = 1; i <= m; i++)
	{
		fin >> a >> b >> c >> z;
		
		v[a].push_back(b);
		v[b].push_back(a);

		maxx[a][b] = c;

		cost[a][b] = realCost[a][b] = z ;
		cost[b][a] = realCost[b][a] = -z ;

	}

}

inline bool CanGoTo(int n1, int n2)
{
	return !(cons[n1][n2] == maxx[n1][n2] || way[n2].n != 0);
}

inline bool comp(Pair a, Pair b)
{
	return a.c > b.c;
}
vector<Pair> que;

Pair tmp, tmp2;
inline void dijkstra()
{


	for (int i = 1; i <= n; i++)
	{
		for (int j = 0; j < v[i].size(); j++)
		{
			cost[i][v[i][j]] += dist[i] - dist[v[i][j]];
		}
	}

	memset(dist, 0x3f, sizeof(dist));
	dist[s] = 0;



	que.push_back( *(new Pair(s,0,s)) );
	int nr = 0;

	while (que.size())
	{
		nr++;
		tmp = que.front();
		
		pop_heap(que.begin(),que.end(),comp);
		que.pop_back();

		if (way[tmp.n].n == 0)
		{
			way[tmp.n] = tmp;

			for (int i = 0; i < v[tmp.n].size(); i++)
			{
				if (CanGoTo(tmp.n, v[tmp.n][i]))
				{
					if (dist[v[tmp.n][i]] > dist[tmp.n] + cost[tmp.n][v[tmp.n][i]])
					{
						dist[v[tmp.n][i]] = dist[tmp.n] + cost[tmp.n][v[tmp.n][i]];

						tmp2.n = v[tmp.n][i];
						tmp2.c = tmp.c + cost[tmp.n][tmp2.n];
						tmp2.ant = tmp.n;

						que.push_back(tmp2);
						push_heap(que.begin(), que.end(), comp);
					}
				}
			}

		}

	}

	return;
}


int dfs(int n)
{
	int a = MaxFlux;

	while (n != way[n].ant)
	{
		a = min(a, maxx[way[n].ant][n] - cons[way[n].ant][n]);
		n = way[n].ant;
	}
	return a;
}


void saturate(int x, int n)
{
	while (n != way[n].ant)
	{
		cons[way[n].ant][n] += x;
		cons[n][way[n].ant] -= x;
		n = way[n].ant;
	}
}

bool find()
{
	memset(way, 0, sizeof(way));

	dijkstra();
	que.clear();

	if (!way[d].n)
		return false;

	int a = dfs(d);

	_cost += dist[d];

	S += _cost * a;
	saturate(a,d);


	return true;

}



void BellmanFord()
{
	memset(dist, 0x3f, sizeof(dist));
	bool ok = 1;

	dist[s] = 0;
	for (int j = 1; j <= n && ok; j++) {

		ok = 0;
		for (int nod = 1; nod <= n; nod++)
			for (i = 0; i<v[nod].size(); i++)
				if (maxx[nod][v[nod][i]]>0 && dist[nod] + cost[nod][v[nod][i]]<dist[v[nod][i]]) {
					dist[v[nod][i]] = dist[nod] + cost[nod][v[nod][i]];
					ok = 1;
				}
	}

	_cost = dist[d];
}

void think()
{
	BellmanFord();
	while (find());
	
}

int main()
{
	_read();

	think();

	fout << S;
    return 0;
}