Cod sursa(job #141641)

Utilizator vlad.maneaVlad Manea vlad.manea Data 23 februarie 2008 15:03:46
Problema Cc Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 1.72 kb
#include <stdio.h>
#include <values.h>

#define nmax 222

int N, ans;

int cst[nmax][nmax], cap[nmax][nmax];

int cat[nmax], uni[nmax], viz[nmax];

int nod[nmax*nmax];

void read()
{
	int i, j;
	freopen("cc.in", "r", stdin);
	scanf("%d", &N);
	for (i = 1; i <= N; ++i)
		for (j = 1; j <= N; ++j)
			scanf("%d", &cst[i][j+N]);
}

int dfs()
{
	int i, j, ic, sc, suma, flux;

	cat[uni[0] = nod[ic = sc = 0] = suma = 0] = MAXINT/2;
	for (i = 1; i <= N+N+1; ++i)
		uni[i] = cat[i] = viz[i] = MAXINT/2;

	viz[0] = -1;

	while (ic <= sc)
	{
		i = nod[ic++];
		for (j = 0; j <= N+N+1; j++)
			if (cap[i][j] > 0 && uni[i] + cst[i][j] < uni[j])
			{
				nod[++sc] = j;
				viz[j] = i;
				uni[j] = uni[i] + cst[i][j];
				cat[j] = cat[i] < cap[i][j]? cat[i]: cap[i][j];
			}
	}

	if (viz[N+N+1] == MAXINT/2)
		return 1;

	for (j = N+N+1, flux = cat[N+N+1]; viz[j] != -1; j = viz[j])
	{
		i = viz[j];
		cap[i][j] -= flux;
		cap[j][i] += flux;
	}

	for (i = N+1; i <= N+N; ++i)
		suma += cap[N+N+1][i];

	if (suma < N)
		return 1;

	return 0;
}

void solve()
{
	int i, j;

	// nodul 0 = sursa
	for (i = 1; i <= N; ++i)
		cap[0][i] = 1;

	// nodul 2N+1 = destinatia
	for (i = N+1; i <= N+N; ++i)
		cap[i][N+N+1] = 1;

	// intre nodurile din 1..N si N+1..2N
	for (i = 1; i <= N; ++i)
		for (j = N+1; j <= N+N; ++j)
		{
			cap[i][j] = 1;
			cst[j][i] = -cst[i][j];
		}

	while (dfs());

	// calculez costurile, ca fiind costurile realizate intre i si j
	for (i = 1; i <= N; ++i)
		for (j = N+1; j <= N+N; ++j)
			ans += cst[i][j] * cap[j][i];
}

void write()
{
	freopen("cc.out", "w", stdout);
	printf("%d\n", ans);
}

int main()
{
	read();
	solve();
	write();

	return 0;
}