Cod sursa(job #831149)

Utilizator alex_unixPetenchea Alexandru alex_unix Data 8 decembrie 2012 10:49:44
Problema Flux maxim de cost minim Scor 70
Compilator cpp Status done
Runda Arhiva educationala Marime 4.65 kb

#include <cstdio>

const int MAX_SIZE(351);
const int MAX_VALUE(1 << 30);
const int MAX_CAPACITY(10000);

int n, m, source, sink, min_cost;
long long maxflow;

int cost [MAX_SIZE] [MAX_SIZE];
int capacity [MAX_SIZE] [MAX_SIZE];
int min_path [MAX_SIZE];
int heap [MAX_SIZE], heap_size;
int heap_position [MAX_SIZE];
int queue [MAX_SIZE * MAX_SIZE];
bool in_queue [MAX_SIZE];
int pred [MAX_SIZE];

struct edge
{
	int node;
	struct edge *next;
} *graph [MAX_SIZE];

inline void add (int x, int y)
{
	struct edge *new_edge(new struct edge);
	new_edge->node = y;
	new_edge->next = graph[x];
	graph[x] = new_edge;
}

inline void read (void)
{
	std::freopen("fmcm.in","r",stdin);
	std::scanf("%d %d %d %d",&n,&m,&source,&sink);
	int x, y, c, z;
	for (int counter(0) ; counter < m ; ++counter)
	{
		std::scanf("%d %d %d %d",&x,&y,&c,&z);
		add(x,y);
		add(y,x);
		capacity[x][y] = c;
		cost[x][y] = z;
		cost[y][x] = -z;
	}
	std::fclose(stdin);
}

inline void print (void)
{
	std::freopen("fmcm.out","w",stdout);
	std::printf("%lld\n",maxflow);
	std::fclose(stdout);
}

inline void BellmanFord (void)
{
	for (int index(1) ; index <= n ; ++index)
		min_path[index] = MAX_VALUE;
	min_path[source] = 0;
	*queue = source;
	in_queue[source] = true;
	int *pop(queue), *push(queue + 1), vertex, neighbor;
	struct edge *iterator;
	while (pop < push)
	{
		vertex = *pop;
		++pop;
		for (iterator = graph[vertex] ; iterator ; iterator = iterator->next)
			if (capacity[vertex][iterator->node] && min_path[vertex] + cost[vertex][iterator->node] < min_path[iterator->node])
			{
				neighbor = iterator->node;
				min_path[neighbor] = min_path[vertex] + cost[vertex][neighbor];
				if (!in_queue[neighbor])
				{
					*push = neighbor;
					++push;
					in_queue[neighbor] = true;
				}
			}
		in_queue[vertex] = false;
	}
	min_cost = min_path[sink];
}

inline void initialize (void)
{
	int index;
	struct edge *iterator;
	for (index = 1 ; index <= n ; ++index)
		if (min_path[index] != MAX_VALUE)
			for (iterator = graph[index] ; iterator ; iterator = iterator->next)
				if (min_path[iterator->node] != MAX_VALUE)
					cost[index][iterator->node] += min_path[index] - min_path[iterator->node];
	for (index = 1 ; index <= n ; ++index)
	{
		min_path[index] = MAX_VALUE;
		heap[index - 1] = index;
		heap_position[index] = index - 1;
	}
	min_path[source] = 0;
	if (source > 1)
	{
		*heap = source;
		heap_position[source] = 0;
		heap[source - 1] = 1;
		heap_position[1] = source - 1;
	}
	heap_size = n;
}

inline void swap (int &a, int &b)
{
	int temp(a);
	a = b;
	b = temp;
}

inline void up (int index)
{
	if (index)
	{
		int father((index - 1) >> 1), vertex(heap[index]);
		while (true)
		{
			if (min_path[vertex] < min_path[heap[father]])
			{
				heap[index] = heap[father];
				swap(heap_position[heap[father]],heap_position[vertex]);
			}
			else
				break;
			index = father;
			if (father)
			{
				--father;
				father >>= 1;
			}
			else
				break;
		}
		heap[index] = vertex;
	}
}

inline void down (int index)
{
	int left((index << 1) + 1), right(left + 1), smallest;
	while (true)
	{
		if (left < heap_size && min_path[heap[left]] < min_path[heap[index]])
			smallest = left;
		else
			smallest = index;
		if (right < heap_size && min_path[heap[right]] < min_path[heap[smallest]])
			smallest = right;
		if (smallest == index)
			break;
		swap(heap_position[heap[smallest]],heap_position[heap[index]]);
		swap(heap[index],heap[smallest]);
		index = smallest;
		left = (index << 1) + 1;
		right = left + 1;
	}
}

inline void pop (void)
{
	--heap_size;
	*heap = heap[heap_size];
	down(0);
}

inline void Dijkstra (void)
{
	initialize();
	int vertex, neighbor;
	struct edge *iterator;
	while (heap_size)
	{
		vertex = *heap;
		pop();
		for (iterator = graph[vertex] ; iterator ; iterator = iterator->next)
			if (capacity[vertex][iterator->node] && min_path[vertex] + cost[vertex][iterator->node] < min_path[iterator->node])
			{
				neighbor = iterator->node;
				min_path[neighbor] = min_path[vertex] + cost[vertex][neighbor];
				pred[neighbor] = vertex;
				up(heap_position[neighbor]);
			}
	}
}

inline void FordFulkerson (void)
{
	int vertex, path_capacity;
	while (true)
	{
		Dijkstra();
		if (min_path[sink] == MAX_VALUE)
			break;
		min_cost += min_path[sink];
		path_capacity = MAX_CAPACITY;
		for (vertex = sink ; vertex != source ; vertex = pred[vertex])
			if (capacity[pred[vertex]][vertex] < path_capacity)
				path_capacity = capacity[pred[vertex]][vertex];
		for (vertex = sink ; vertex != source ; vertex = pred[vertex])
		{
			capacity[pred[vertex]][vertex] -= path_capacity;
			capacity[vertex][pred[vertex]] += path_capacity;
		}
		maxflow += min_cost * path_capacity;
	}
}

int main (void)
{
	read();
	BellmanFord();
	FordFulkerson();
	print();
}