Cod sursa(job #499513)

Utilizator vlad_DVlad Dumitriu vlad_D Data 10 noiembrie 2010 04:45:18
Problema Cuplaj maxim de cost minim Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 2.07 kb
#include <cstdio>
#include <algorithm>

using namespace std;
int n, m, e;
int v[301][301];
int g[301][301];
int r[301], l[301]; // for matching
int vr[301], vc[301]; //deltas
int cr[301], cc[301]; //covered?
int p[301]; //partial
void find_zero() {
	int i, j, mn;
	for (mn = 50000, i = 1; i <= n; ++i) if (!cr[i])
		for (j = 1; j <= n; ++j) if (!cc[j])
			mn = min(g[i][j] + vr[i] + vc[j], mn);

	for (i = 1; i <= n; ++i) {
		if (cr[i]) vr[i] += mn;
		if (!cc[i]) vc[i] -= mn;
	}
	for (i = 1; i <= n; ++i) if (!cr[i])
		for (j = 1; j <= n; ++j) if (!cc[j] && g[i][j] + vr[i] + vc[j] ==
				0) {
			if (r[i]) {
				p[i] = j; cr[i] = 1; cc[r[i]] = 0;
				break;
			} else {
				int aux;
				do {aux = l[j]; r[i] = j; l[j] = i; i = aux; j = p[i];}
				while (aux);
				return;
			}
		}
	find_zero();
}
int main() {
	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);
		c -= 20001;
		v[a][b] = i;
		g[a][b] = c;
	}
	n = max(n, m);
	//intai bagam noi
	for (int i = 1; i <= n; ++i) {
		int mn = g[i][1] + vr[i] + vc[1];
		for (int j = 1; j <= n; ++j) mn = min(mn, g[i][j] + vr[i] + vc[j]);
		vr[i] -= mn;
	}
	for (int j = 1; j <= n; ++j) {
		int mn = g[1][j] + vr[1] + vc[j];
		for (int i = 1; i <= n; ++i) mn = min(mn, g[i][j] + vr[i] + vc[j]);
		vc[j] -= mn;
	}
	int cnt = 0;
	for (int i = 1; i <= n; ++i)
		for (int j = 1; j <= n; ++j) if (g[i][j] + vr[i] + vc[j] == 0)
			if (r[i] == 0 && l[j] == 0) {
				r[i] = j; l[j] = i;
				++cnt;
			}
	for (; cnt < n; ++cnt) {
		for (int i = 1; i <= n; ++i) {
			cr[i] = p[i] = 0;
			cc[i] = l[i];
		}
		find_zero();
	for (int i = 1; i <= n; ++i)
		for (int j = 1; j <= n; ++j) if (g[i][j] + vr[i] + vc[j] == 0)
			if (r[i] == 0 && l[j] == 0) {
				r[i] = j; l[j] = i;
				++cnt;
			}

	}
	int nr = 0, k = 0;
	for (int i = 1; i <= n; ++i) if (r[i] && g[i][r[i]]) {
		++nr;
		k += g[i][r[i]] + 20001;
	}
	printf("%d %d\n", nr, k);
	for (int i = 1; i <= n; ++i) if (r[i] && g[i][r[i]]) {
		printf("%d ", v[i][r[i]]);
	}
	if (nr) printf("\n");
	return 0;
}