Cod sursa(job #135983)

Utilizator bogdan2412Bogdan-Cristian Tataroiu bogdan2412 Data 14 februarie 2008 22:08:45
Problema Paznici2 Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.64 kb
#include <cstdio>
#include <queue>

using namespace std;

#define MAXN 405

int N, cst[MAXN][MAXN], c[MAXN][MAXN];

int val[MAXN];
int cup[MAXN];

char good[MAXN][MAXN];

#define IN(i) (i)
#define OUT(i) ((i) + N)
int SRC, DST;

int F = 0, CST = 0;

int d[MAXN], p[MAXN]; char in[MAXN];

queue<int> Q;

inline void update( int nod, int Cst, int par )
{
	if (Cst >= d[nod])
		return;

	// Cst < d[nod]
	d[nod] = Cst;
	p[nod] = par;
	if (!in[nod])
		Q.push(nod),
		in[nod] = 1;
}

inline int bf()
{
	memset( d, 0x3f, sizeof(d) );
	memset( p, -1, sizeof(p) );

	d[SRC] = 0; Q.push(SRC); in[SRC] = 1;
	for (; !Q.empty(); Q.pop())
	{
		int i = Q.front(), type = 0;
		if (1 <= i)
			type = 1;
		if (N + 1 <= i)
			type = 2;
		if (i == DST)
			type = 3;

		if (type == 0 || type == 2)
			for (int j = 1; j <= N; j++)
				if (c[i][j])
					update( j, d[i] + cst[i][j], i );
		if (type == 1)
			for (int j = N + 1; j <= N + N; j++)
				if (c[i][j])
					update( j, d[i] + cst[i][j], i );
		if (type == 2)
			if (c[i][DST])
				update( DST, d[i] + cst[i][DST], i );


		in[i] = 0;
	}

	return (d[DST] != 0x3f3f3f3f);
}

inline void bfRight( int S )
{
	memset( d, 0x3f, sizeof(d) );
	memset( p, -1, sizeof(p) );

	d[S] = 0; Q.push(S); in[S] = 1;
	for (; !Q.empty(); Q.pop())
	{
		int i = Q.front(), type = 1;
		if (N + 1 <= i)
			type = 2;

		if (type == 1)
			for (int j = N + 1; j <= N + N; j++)
				if (!c[i][j])
					update( j, d[i] + cst[j][i], i );
		if (type == 2)
			for (int j = 1; j <= N; j++)
				if (!c[i][j])
					update( j, d[i] + cst[j][i], i );

		in[i] = 0;
	}
}

int main()
{
	freopen("paznici2.in", "rt", stdin);
	freopen("paznici2.out", "wt", stdout);

	scanf("%d", &N); SRC = 0; DST = N + N + 1;
	for (int i = 1; i <= N; i++)
	{
		c[SRC][ IN(i) ] = 1;
		c[ OUT(i) ][DST] = 1;
		for (int j = 1; j <= N; j++)
		{
			scanf("%d", cst[ IN(i) ] + OUT(j));
			cst[ OUT(j) ][ IN(i) ] = -cst[ IN(i) ][ OUT(j) ];
			c[ IN(i) ][ OUT(j) ] = 1;
		}
	}

	for (; bf(); F++, CST += d[DST])
		for (int j = DST; j != SRC; j = p[j])
			c[ p[j] ][j]--,
			c[j][ p[j] ]++;

	for (int i = 1; i <= N; i++)
		for (int j = 1; j <= N; j++)
			if (!c[ IN(i) ][ OUT(j) ])
			{
				cup[ IN(i) ] = OUT(j);
				cup[ OUT(j) ] = IN(i);
				break;
			}
	printf("%d\n", CST);
	for (int i = 1; i <= N; i++)
	{
		bfRight( cup[ IN(i) ] );

		//trebuie afisat invers...
		for (int j = 1; j <= N; j++)
			if (d[ OUT(j) ] + cst[ IN(i) ][ OUT(j) ] - cst[ IN(i) ][ cup[ IN(i) ] ] == 0)
				good[j][i] = 1;
	}

	for (int i = 1; i <= N; i++)
	{
		int Nr = 0;
		for (int j = 1; j <= N; j++)
			Nr += good[i][j];
		printf("%d", Nr);
		for (int j = 1; j <= N; j++)
			if (good[i][j])
				printf(" %d", j);
		printf("\n");
	}

	return 0;
}