Cod sursa(job #714949)

Utilizator eukristianCristian L. eukristian Data 16 martie 2012 12:58:43
Problema Cuplaj maxim de cost minim Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 2.67 kb
#include <stdio.h>
#include <stdlib.h>
#include <vector>
using namespace std;

#define MAXN 710
#define source 0
#define sink 709
#define INF 0x7fffffff

int n, m, e;
int edge[MAXN][MAXN], dist[MAXN];

int flow[MAXN][MAXN], capacity[MAXN][MAXN], queue[MAXN * MAXN], prev[MAXN];
bool in_queue[MAXN];

vector<int> v[MAXN], cost[MAXN];

void read();
void solve();
int bfc()
{
	int left = 0, right = 0;
	queue[0] = source;
	
	for (int i = 1 ; i <= n + m ; ++i)
	{
		dist[i] = INF;
		in_queue[i] = false;
		prev[i] = -1;
	}
	
	dist[sink] = INF;
	in_queue[sink] = false;
	prev[sink] = -1;
	
	dist[source] = 0;
	in_queue[source] = true;
	prev[source] = -1;
	
	while (left <= right)
	{
		int nd = queue[left++];
		
		int len = v[nd].size();
		for (int i = 0 ; i < len ; ++i)
		{
			if (dist[v[nd][i]] > dist[nd] + cost[nd][i] && capacity[nd][v[nd][i]] - flow[nd][v[nd][i]] > 0)
			{
				dist[v[nd][i]] = dist[nd] + cost[nd][i];
				prev[v[nd][i]] = nd;
				
				if (!in_queue[v[nd][i]])
				{
					queue[++right] = v[nd][i];
					in_queue[v[nd][i]] = true;
				}
			}
		}
		
		in_queue[nd] = false;
	}
	
	if (dist[sink] != INF)
	{
		int minIncrease = INF;
		for (int crt = sink ; crt != source ; crt = prev[crt])
			if (minIncrease > capacity[prev[crt]][crt] - flow[prev[crt]][crt])
				minIncrease = capacity[prev[crt]][crt] - flow[prev[crt]][crt];
		
		for (int crt = sink ; crt != source ; crt = prev[crt])
		{
			flow[prev[crt]][crt] += minIncrease;
			flow[crt][prev[crt]] -= minIncrease;
		}
		
		return dist[sink] * minIncrease;
	}
	
	return 0;
}

int main()
{
	read();
	solve();
	
	return 0;
}

void read()
{
	freopen("cmcm.in", "r", stdin);
	freopen("cmcm.out","w", stdout);
	
	scanf("%d%d%d", &n, &m, &e);
	
	for (int i = 1 ; i <= e ; ++i)
	{
		int a, b, c;
		scanf("%d%d%d", &a, &b, &c);
		
		v[a].push_back(b + n);cost[a].push_back(c);
		v[b + n].push_back(a);cost[b + n].push_back(-c);
		
		capacity[a][b + n] = 1;
		edge[a][b + n] = i;
	}
	
	for (int i = 1 ; i <= n ; ++i)
	{
		v[source].push_back(i);cost[source].push_back(0);
		v[i].push_back(source);cost[i].push_back(0);
		capacity[source][i] = 1;
	}
	
	for (int i = n + 1 ; i <= n + m ; ++i)
	{
		v[sink].push_back(i);cost[sink].push_back(0);
		v[i].push_back(sink);cost[i].push_back(0);
		capacity[i][sink] = 1;
	}
}

void solve()
{
	int totalCost = 0, crtCost, nr = 0;
	while (crtCost = bfc())
		totalCost += crtCost;
		
	for (int i = 1 ; i <= n ; ++i)
		for (int j = n + 1 ; j <= n + m ; ++j)
			if (capacity[i][j] && flow[i][j])
			{	
				nr++;break;
			}
			
	printf("%d %d\n", nr, totalCost);
	
	for (int i = 1 ; i <= n ; ++i)
		for (int j = n + 1 ; j <= n + m ; ++j)
			if (capacity[i][j] && flow[i][j])
			{	
				printf("%d ", edge[i][j]);break;
			}
	printf("\n");
}