Cod sursa(job #371522)

Utilizator savimSerban Andrei Stan savim Data 5 decembrie 2009 17:10:35
Problema Cuplaj maxim de cost minim Scor Ascuns
Compilator cpp Status done
Runda Marime 2.2 kb
#include <stdio.h>
#include <string.h>
#include <algorithm>

using namespace std;

#define MAX_N 710
#define inf 2000000000
#define pb push_back

int n, m, e, k, dest, sol, nr, improve;
int tata[MAX_N], dist[MAX_N];
int C[MAX_N][MAX_N], F[MAX_N][MAX_N], edge[MAX_N][MAX_N];

struct muchie {
	int a, b, c;
} v[120010];

void cit() {
	scanf("%d %d %d", &n, &m, &e);
	for (int i = 1; i <= e; i++) {
		k++;
    	scanf("%d %d %d", &v[k].a, &v[k].b, &v[k].c);
		v[k].a++; v[k].b += n + 1;
		edge[v[k].a][v[k].b] = i;
		C[v[k].a][v[k].b] = 1;

		k++;
		v[k] = v[k - 1]; 
		swap(v[k].a, v[k].b);
		v[k].c *= (-1);
	}
}

void build_graph() {
	//sursa este nodul 1, destinatia n + m + 2
	dest = n + m + 2;
	for (int i = 2; i <= n + 1; i++) {
		v[++k].a = 1; v[k].b = i;
		v[++k].a = i; v[k].b = 1;

		C[1][i] = 1;
	}
	for (int i = n + 2; i <= n + m + 1; i++) {
		v[++k].a = i; v[k].b = dest;
		v[++k].a = dest; v[k].b = i;	
	
		C[i][dest] = 1;
	}
}

void relax(int u, int v, int val) {
	if (dist[u] != inf && C[u][v] > F[u][v] && dist[v] > dist[u] + val) {
    	dist[v] = dist[u] + val;
		tata[v] = u;
	}
}

int bellman_ford() {
	for (int i = 1; i <= dest; i++) {
    	dist[i] = inf;
		tata[i] = -1;
	}
	dist[1] = 0;

	for (int i = 0; i <= n; i++)
		for (int j = 1; j <= k; j++)
			relax(v[j].a, v[j].b, v[j].c);

    if (dist[dest] < inf) {
		int flux = inf;
		for (int i = dest; i != 1; i = tata[i])
			flux = min(flux, C[tata[i]][i] - F[tata[i]][i]);

		for (int i = dest; i != 1; i = tata[i]) {
			F[tata[i]][i] += flux;
			F[i][tata[i]] -= flux;
		}

		return flux * dist[dest];	 
	}
	return 0;
}

void solve() {
	//construiesc graful de flux
	build_graph();

	improve = 1;
	while (improve) {
    	improve = bellman_ford();
		sol += improve;
    }  
}

void write() {
	for (int i = 2; i <= n + 1; i++)
		for (int j = n + 2; j < dest; j++)
			if (C[i][j] && F[i][j]) {
				nr++;
				break;
			}

	printf("%d %d\n", nr, sol);
    for (int i = 2; i <= n + 1; i++)
        for (int j = n + 2; j < dest; j++)
            if (C[i][j] && F[i][j]) {
				printf("%d ", edge[i][j]);
                break;
            }
	printf("\n"); 
}

int main() {
	freopen("cmcm.in", "r", stdin);
	freopen("cmcm.out", "w", stdout);

	cit();
	solve();
	write();

	return 0;
}