Cod sursa(job #116974)

Utilizator Binary_FireFlorin Pogocsan Binary_Fire Data 20 decembrie 2007 00:55:52
Problema Gather Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 3.28 kb
#include <cstdio>
#include <vector>

using namespace std;

#define fin  "gather.in"
#define fout "gather.out"

#define sz(x) (int)((x).size())
#define pb push_back

#define DxBG
#define FL

const int Nmax = 1000;
const unsigned int MAX  = ( ( 1 << 32 ) - 1);

int N,M,K;
vector <int> g[Nmax],c[Nmax],d[Nmax];
vector <int> detinut;
unsigned int minc[Nmax],dist[16][16][16];

unsigned int dp[15][1<<15];
int nrb[1<<16];

int dim,heap[Nmax];
int poz[Nmax];

void readdata()
{
	int i,x,y,cost,capac;

	freopen(fin,"r",stdin);

	scanf("%d%d%d",&K,&N,&M);

	for (i=1;i<=K;++i)
	{
		scanf("%d",&x);
		detinut.pb(x);		
	}

	for ( i = 1 ; i <= M ; ++i )
	{
		scanf("%d%d",&x,&y);
		scanf("%d%d",&cost,&capac);

		g[x].pb(y); c[x].pb(cost); d[x].pb(capac);
		g[y].pb(x); c[y].pb(cost); d[y].pb(capac);
	}
}

void reconst_heap(int p)
{
	int minim;

	if ( minc[ heap[2*p] ] < minc[ heap[2*p+1] ])
		minim = 2 * p;
	else
		minim = 2 * p + 1;

	if ( minc[ heap[p] ] > minc[ heap[minim] ] && minim <= dim )
	{
		swap( poz[ heap[p] ] , poz[ heap[minim] ] );
		swap( heap[ p ] , heap[ minim ] );
	   	reconst_heap(minim);	
	}
}

void urca(int p)
{
	if ( p / 2 >= 1 && minc[ heap[p] ] < minc[ heap[p/2] ] )
	{
		swap( heap[p] , heap[p/2] );
		swap( poz[ heap[p] ]  , poz[ heap[p/2] ] );
		urca( p/2 );
	}
}

void dijkstra(int sursa,int nrdet)
{
	int i,x;

	for ( i = 1 ; i <= N ; ++i )
	{
		minc[i]=MAX;
		poz[i] = 0;
	}

	minc[sursa] = 0;
	poz[sursa] = 1;
	heap[1] = sursa;
	dim = 1 ;

	while ( dim > 0 )
	{
		x = heap[1];

		heap[1] = heap[dim];
		--dim;
		reconst_heap(1);

		for ( i = 0 ; i < sz(g[x]); ++i )
		{
			if ( nrdet <= d[x][i] && ( minc[x] + c[x][i] < minc[ g[x][i] ] || poz[ g[x][i] ] == 0 ) )
			{
				minc[ g[x][i] ] = minc[x] + c[x][i];
				if ( poz[ g[x][i] ] == 0 )
				{
					++dim;
					poz[ g[x][i] ] = dim;
					heap[dim] = g[x][i];
					urca( dim );
				}
				else
					urca( poz[ g[x][i] ] );
			}
		}
	}
}

void solve()
{
	int i,j,k;
	unsigned int ret;

	for ( i = 0; i < sz(detinut) ; ++i )
	for ( j = 1; j <= K ; ++j )
	{
		dijkstra(detinut[i],j);
		for ( k = 0 ; k < sz(detinut); ++k)
			dist[ i ][ k ][ j ] = minc[ detinut[k] ];
#ifdef DBG
		printf("%d %d\n",detinut[i],j);
		for ( k = 0 ; k < sz(detinut) ; ++k )
			printf("%u ",dist[i][k][j]);
		printf("\n\n");
#endif
	}

	dijkstra(1,0);

	for ( i = 0 ; i < sz(detinut) ; ++i )
	for ( j = 0 ; j <  ( 1 << K ) ; ++j )
		dp[i][j] = MAX;

	for ( i = 0 ; i < sz(detinut) ; ++i )
		dp[i][1<<i] = minc[ detinut[i] ];

	for ( i = 0 ; i < ( 1 << K ) ; ++i )
	{
		for ( j = 0 ; ( 1 << j ) <= i ; ++j )
			if ( ( 1 << j ) & i )
			   ++nrb[i];	
	}

	for ( k = 0 ; k < ( 1 << K ) ; ++k )
	{
		for ( i = 0 ; i < sz(detinut) ; ++i )
			if ( ( k & ( 1 << i ) ) == 0 )
			{
				for ( j = 0 ; j < sz(detinut) ; ++j )
					if ( ( k & ( 1 << j ) ) && dist[i][j][nrb[k]] < MAX )
						dp[i][k | ( 1 << i ) ] = min( dp[i][k | ( 1 << i ) ] , (nrb[k]+1)*dist[i][j][nrb[k]] + dp[j][k]);
			}
	}

	ret = dp[0][(1<<K)-1];

	for ( i = 0 ; i < sz(detinut) ; ++i )
		ret = min( ret , dp[i][(1<<K)-1] );

#ifdef DBG
	for ( i = 0 ; i < sz(detinut) ; ++i )
	{
		for ( j = 0 ; j <  ( 1 << K ) ; ++j )
			if ( dp[i][j] < MAX ) printf("%u ",dp[i][j]);
			else
				printf("0 ");
		printf("\n");
	}
#endif

#ifdef FL
	freopen(fout,"w",stdout);
#endif

	printf("%u\n",ret);
}

int main()
{
	readdata();
	solve();
	return 0;
}