Cod sursa(job #833062)

Utilizator alex_unixPetenchea Alexandru alex_unix Data 11 decembrie 2012 20:53:22
Problema Cuplaj maxim de cost minim Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 2.69 kb

#include <cstdio>
#include <cstring>
#include <vector>

const int MAX_SIZE(602);
const int MAX_COST(1 << 30);

int vertices, source, sink, l, r, e, maxflow, min_cost;

int capacity [MAX_SIZE] [MAX_SIZE];
int cost [MAX_SIZE] [MAX_SIZE];
int min_path [MAX_SIZE];
int queue [MAX_SIZE * MAX_SIZE], *pop, *push;
int pred [MAX_SIZE];
bool in_queue [MAX_SIZE];
int edges [MAX_SIZE] [MAX_SIZE];
std::vector<int> graph [MAX_SIZE];

inline void read (void)
{
	std::freopen("cmcm.in","r",stdin);
	std::scanf("%d %d %d",&l,&r,&e);
	vertices = l + r;
	source = 0;
	sink = vertices + 1;
	int x, y, c;
	for (int counter(1) ; counter <= e ; ++counter)
	{
		std::scanf("%d %d %d",&x,&y,&c);
		y += l;
		graph[x].push_back(y);
		graph[y].push_back(x);
		edges[x][y] = counter;
		cost[x][y] = c;
		cost[y][x] = -c;
		capacity[x][y] = 1;
		graph[source].push_back(x);
		graph[y].push_back(sink);
		capacity[source][x] = 1;
		capacity[y][sink] = 1;
	}
	std::fclose(stdin);
}

inline void initialize (void)
{
	std::memset(pred,0,sizeof(*pred) * (sink + 1));
	std::memset(in_queue,0,sizeof(*in_queue) * (sink + 1));
	for (int index(source) ; index <= sink ; ++index)
		min_path[index] = MAX_COST;
	in_queue[source] = true;
	min_path[source] = 0;
	*queue = source;
	pop = queue;
	push = queue + 1;
}

inline void BellmanFord (void)
{
	initialize();
	int vertex, neighbor, index, size;
	while (pop < push)
	{
		vertex = *pop;
		++pop;
		for (index = 0, size = graph[vertex].size() ; index < size ; ++index)
			if (capacity[vertex][graph[vertex][index]] && min_path[vertex] + cost[vertex][graph[vertex][index]] < min_path[graph[vertex][index]])
			{
				neighbor = graph[vertex][index];
				min_path[neighbor] = min_path[vertex] + cost[vertex][neighbor];
				pred[neighbor] = vertex;
				if (!in_queue[neighbor])
				{
					*push = neighbor;
					++push;
					in_queue[neighbor] = true;
				}
			}
		in_queue[vertex] = false;
	}
}

inline void FordFulkerson (void)
{
	int vertex;
	while (true)
	{
		BellmanFord();
		if (!pred[sink])
			break;
		for (vertex = sink ; vertex != source ; vertex = pred[vertex])
		{
			capacity[pred[vertex]][vertex] = 0;
			capacity[vertex][pred[vertex]] = 1;
		}
		min_cost += min_path[sink];
		++maxflow;
	}
}

inline void print (void)
{
	std::freopen("cmcm.out","w",stdout);
	int i, j;
	std::printf("%d %d\n",maxflow,min_cost);
	for (i = 1 ; i <= l ; ++i)
		for (j = l + 1 ; j <= vertices ; ++j)
			if (edges[i][j])
				if (!capacity[i][j])
				{
					std::printf("%d ",edges[i][j]);
					break;
				}
	std::putchar('\n');
	std::fclose(stdout);
}

int main (void)
{
	read();
	FordFulkerson();
	print();
	return 0;
}