Cod sursa(job #714185)

Utilizator eukristianCristian L. eukristian Data 15 martie 2012 15:17:16
Problema Cuplaj maxim de cost minim Scor 20
Compilator cpp Status done
Runda Arhiva educationala Marime 2.39 kb
#include <cstdio>
#include <vector>
#include <bitset>
#define MAXN 602
#define source 0
#define sink 601

using namespace std;
vector<pair <int, int> > G[MAXN];
char capacity[MAXN][MAXN], flow[MAXN][MAXN];
unsigned short prev[MAXN], queue[MAXN];
int dist[MAXN], edge[MAXN][MAXN];

int n, m, e;

bool bfs()
{
	int left = 0, right = 0;

	for (int i = 1 ; i <= n + m ; ++i)
		dist[i] = 0x7fffffff;
	dist[sink] = 0x7fffffff;
	dist[source] = 0;
	
	queue[left] = source;
	bitset<MAXN> in_queue(false);
	in_queue[source] = 1;
	
	while (left <= right)
	{
		int nd = queue[left++];
		
		vector<pair <int, int> >::iterator it;
		for (it = G[nd].begin() ; it != G[nd].end() ; ++it)
		{
			if ((dist[it->first] > dist[nd] + it->second) && (flow[nd][it->first] < capacity[nd][it->first]))
			{
				dist[it->first] = dist[nd] + it->second;
				prev[it->first] = nd;
				if (!in_queue[it->first])
				{
					queue[++right] = it->first;
					in_queue[it->first] = true;
				}
			}
		}
		in_queue[nd] = false;
	}
	
	return dist[sink] < 0x7fffffff;
	
}

int main()
{
	freopen("cmcm.in", "r", stdin);
	freopen("cmcm.out","w",stdout);
	
	scanf("%d %d %d\n", &n, &m, &e);
	
	for (int i = 1 ; i <= e ; ++i)
	{
		int a, b, c;
		scanf("%d %d %d", &a, &b, &c);
		G[a].push_back(make_pair(b + n, c));
		G[b + n].push_back(make_pair(a, -c));
		capacity[a][b + n] = 1;
		edge[a][b + n] = i;
	}
	
	for (int i = 1 ; i <= n ; ++i)
	{
		G[source].push_back(make_pair(i, 0)), capacity[source][i] = 1;
		G[i].push_back(make_pair(source, 0));
	}
	for (int i = n + 1 ; i <= n + m	; ++i)
	{	
		G[i].push_back(make_pair(sink, 0)), capacity[i][sink] = 1;
		G[sink].push_back(make_pair(i, 0));
	}
	
	int totalFlow = 0, sol = 0, nr = 0;
	
	while (bfs())
	{
		int minResVal = 0x7fffffff;
		for (int i = sink ; i != 0 ; i = prev[i])
			if (minResVal > capacity[prev[i]][i] - flow[prev[i]][i])
				minResVal = capacity[prev[i]][i] - flow[prev[i]][i];
		for (int i = sink ; i != 0 ; i = prev[i])
		{
			flow[i][prev[i]] -= minResVal;
			flow[prev[i]][i] += minResVal;
		}
		
		totalFlow += minResVal;
		sol += minResVal * dist[sink];
	}
		
	for (int i = 1 ; i <= n ; ++i)
		for (int j = n + 1 ; j <= m + n ; ++j)
			if (capacity[i][j] && flow[i][j])
			{
				nr++;
				break;
			}
			
	printf("%d %d\n", nr, sol);
	for (int i = 1 ; i <= n ; ++i)
		for (int j = n + 1 ; j <= m + n ; ++j)
			if (capacity[i][j] && flow[i][j])
			{
				printf("%d ", edge[i][j]);
				break;
			}
	
	
	return 0;
}