Cod sursa(job #1659517)

Utilizator vladttturcuman vlad vladtt Data 22 martie 2016 12:01:19
Problema Flux maxim de cost minim Scor 0
Compilator cpp Status done
Runda Arhiva educationala Marime 3.17 kb
// Minimum Cost Maximum Flow.cpp : Defines the entry point for the console application.
//

//#include "stdafx.h"
#include <fstream>
#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<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], 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 ;

	}

}

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

bool comp(Pair a, Pair b)
{
	return a.c > b.c;
}

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;

	vector<Pair> que;

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

	Pair tmp,tmp2;

	while (que.size())
	{
		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 (maxx[tmp.n][v[tmp.n][i]]>0 && 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;
}

struct Pair2 {
	int realcost, x;
	Pair2(int _rc,int _x)
	{
		realcost = _rc;
		x = _x;
	}
};

Pair2 dfs(int n)
{
	if (n == s)
		return *(new Pair2(0,MaxFlux));

	Pair2 tmp = dfs(way[n].ant);

	tmp.realcost += realCost[way[n].ant][n];
	tmp.x = min(tmp.x, maxx[way[n].ant][n] - cons[way[n].ant][n]);

	return tmp;
}

void saturate(int x, int n)
{
	if (n == way[n].ant)
		return;

	cons[way[n].ant][n] += x;
	cons[n][way[n].ant] -= x;
	saturate(x,way[n].ant);
}

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

	dijkstra();

	if (dist[n] > 10000000)
		return false;

	
	Pair2 tmp = dfs(d);

	S += tmp.realcost * tmp.x;
	saturate(tmp.x,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;
				}
	}


}

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

int main()
{
	_read();

	think();

	fout << S;
    return 0;
}