Cod sursa(job #787446)

Utilizator danalex97Dan H Alexandru danalex97 Data 13 septembrie 2012 13:42:43
Problema Gather Scor 10
Compilator cpp Status done
Runda Arhiva de probleme Marime 4.49 kb
/*
#include <fstream>
#include <queue>
#include <vector>
using namespace std;

#define nod first.first
#define cost first.second
#define nbr second

#define val first
#define key second

typedef pair<long long,long long> Pair;
typedef pair<Pair,long long> Triple;

const long long Nmax = 755;
const long long Mmax = 1255;
const long long Kmax = 17;
const long long oo = 0x3f3f3f3f;

long long N,M,K,act;
long long Nodes[Kmax];

vector< Triple > Leg[Nmax];

long long D[1<<Kmax][Kmax];
long long Dist[Kmax][Kmax][Kmax];

long long Marked[Nmax],Co;
long long Cost[Nmax];

ifstream F("gather.in");
ofstream G("gather.out");

priority_queue< Pair , vector< Pair > , greater< Pair > > Heap;

int main()
{
	F>>K>>N>>M;
	Nodes[0]=1;
	for (long long i=1;i<=K;++i)
		F>>Nodes[i];
	for (long long i=1;i<=M;++i)
	{
		long long x,y,c,n; 
		F>>x>>y>>c>>n;
		Leg[x].push_back( make_pair( make_pair( y , c ) , n ) );
		Leg[y].push_back( make_pair( make_pair( x , c ) , n ) );
	}
	
	for (long long i=0;i<=K;++i)
		for (long long j=0;j<=K ;++j)
		{
			long long Start = Nodes[i];
			Heap.push( make_pair(0,Start) );
			
			while ( Co < N )
			{
				while ( Marked[ Heap.top().key ] )
					Heap.pop();
				
				long long Nod = Heap.top().key ;
				Marked[ Nod ] = 1, ++Co;
				Cost[ Nod ] = Heap.top().val;
				
				Heap.pop();
				
				for ( vector<Triple>::iterator it=Leg[Nod].begin();it!=Leg[Nod].end();++it )
					if ( !Marked[ it->nod ] && it->nbr >= j )
						Heap.push( make_pair( it->cost + Cost[ Nod ] , it->nod ) );
			}
			
			for (long long k=1;k<=K;++k)
				Dist[i][k][j] = Cost[ Nodes[k] ];
			for (long long k=1;k<=N;++k) Marked[k]=Cost[k]=0;
			
			Co=0;
			
			while ( Heap.size() ) Heap.pop();
		}
	
	for (long long i=1;i<( 1<<K );++i)
	{
		long long det=0;
		for ( long long j=i;j;j>>=1)
            if ( j & 1 ) ++det;
		for ( long long j=1,jj=1;j<=i;j<<=1,++jj)
			if ( j & i )
			{
				D[i][jj]=oo;
				long long Act = i-j;
				if ( Act == 0 )
					D[i][jj]= Nodes[jj] == 1 ? 0 : Dist[0][jj][0];
				else
					for ( long long k=1,kk=1;k<=Act;k<<=1,++kk)
						if ( k & Act )
							D[i][jj]= min ( D[i][jj] , Dist[kk][jj][det-1] * det + D[Act][kk] );
			}
	}
	
	long long Sol=oo;
	for (long long i=1;i<=K;++i)
		Sol=min(Sol,D[(1<<K)-1][i]);
	
	G<<Sol<<'\n';
}
*/
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <queue>

using namespace std;

#define MAX_N 755
#define MAX_K 16

#define FIN "gather.in"
#define FOUT "gather.out"

#define INF 0x3f3f3f3f

#define f first
#define s second

#define mp make_pair
#define pb push_back

int K, N, M, V[MAX_K], D[MAX_K][MAX_K][MAX_N], A[1<<MAX_K][MAX_K], Res;
vector< pair<int, pair<int, int> > > G[MAX_N];
priority_queue< pair<int, int> > Q;

void dijkstra(int src, int limit, int D[])
{
    int n, d, t;
    vector < pair<int, pair<int, int> > >::iterator it;

    memset(D, 0x3f, N*sizeof(D[0]));
    D[src] = 0;

    for (Q.push(mp(0, src)); !Q.empty(); )
    {
        n = Q.top().s; d = -Q.top().f; Q.pop();
        if (D[n] < d) continue;
        for (it = G[n].begin(); it != G[n].end(); ++it)
        {
            if (it->s.s < limit) continue;
            if (D[it->f] > (t = D[n]+it->s.f))
            {
                D[it->f] = t;
                Q.push(mp(-t, it->f));
            }
        }
    }
}

int main()
{
    int i, j, k, a, b, cnt;

    freopen(FIN, "r", stdin);
    freopen(FOUT, "w", stdout);

    scanf("%d %d %d", &K, &N, &M);
    for (++K, i = 1; i < K; ++i)
    {
        scanf("%d", &j);
        V[i] = --j;
    }
    for (; M; --M)
    {
        scanf("%d %d %d %d", &i, &j, &a, &b);
        --i, --j;
        G[i].pb(mp(j, mp(a, b)));
        G[j].pb(mp(i, mp(a, b)));
    }

    for (i = 0; i <= K; ++i)
        for (j = 1; j <= K; ++j)
            dijkstra(V[i], j, D[i][j]);

    memset(A, 0x3f, sizeof(A));
    A[1][0] = 0;
    for (i = 2; i < (1<<K); ++i)
    {
        for (cnt = -1, j = i; j; j &= j-1) ++cnt;
        for (j = 0; j < K; ++j)
        {
            if (!(i&(1<<j))) continue;
            for (k = 0; k < K; ++k)
            {
                if (A[i-(1<<j)][k] == INF || D[k][cnt][V[j]] == INF) continue;
                A[i][j] = min(A[i][j], A[i-(1<<j)][k] + cnt*D[k][cnt][V[j]]);
            }
        }
    }

    Res = A[(1<<K)-1][0];
    for (i = 0; i < K; ++i)
        Res = min(Res, A[(1<<K)-1][i]);
    printf("%d\n", Res);

    return 0;
}