Cod sursa(job #787457)

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

#deFe nod first.first
#deFe cost first.second
#deFe nbr second

#deFe val first
#deFe 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 <fstream>
#include <algorithm>
#include <vector>
#include <set>

using namespace std;

class Triple
{	public:	int p1, p2, p3;	Triple();
	Triple(int _p1, int _p2, int _p3)
	{	p1 = _p1;	p2 = _p2;	p3 = _p3; }
};

typedef pair<int,int> Pair;
#define push_Triple(deFe1, deFe2, deFe3) push_back(Triple(deFe1, deFe2, deFe3))
#define insert_pair(deFe1, deFe2) insert(make_pair(deFe1, deFe2))

const int oo = 0x3f3f3f3f;

int I[16], Drum[1 << 15][16];
int D[16][16][755], Lg[1 << 15]; 
vector<Triple> V[755];

int N, M, K;
set< Pair > S;

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

    Lg[1] = 1;
    for (int i = 2; i < (1 << 15); ++i)
        Lg[i] = Lg[i >> 1] + 1;

    F >> K >> N >> M;
    for (int i = 1; i <= K; ++i)
        F >> I[i];
    for (int i = 1, nod1, nod2, maxp, cost; i <= M; ++i)
    {
        F >> nod1 >> nod2 >> cost >> maxp;
        V[nod1].push_Triple(nod2, cost, maxp);
        V[nod2].push_Triple(nod1, cost, maxp);
    }

    for (int i = 1; i <= K; ++i)
        for (int k = 0; k <= K; ++k)
        {
            for (int j = 1; j <= N; ++j)
                if (j != I[i])
                    D[i][k][j] = oo;
            for (vector<Triple>::iterator it = V[I[i]].begin(); it != V[I[i]].end(); ++it)
                if (k <= it->p3)
                    D[i][k][it->p1] = it->p2;
            for (int j = 1; j <= N; ++j)
                if (j != I[i])
                    S.insert_pair(D[i][k][j], j);

            while (!S.empty())
            {
                Pair now = *S.begin();
                S.erase(S.begin());

                if (now.first > D[i][k][now.second]) continue;

                for (vector<Triple>::iterator it = V[now.second].begin(); it != V[now.second].end(); ++it)
                    if (k <= it->p3)
                        if (D[i][k][now.second] + it->p2 < D[i][k][it->p1])
                        {
                            D[i][k][it->p1] = D[i][k][now.second] + it->p2;
                            S.insert_pair(D[i][k][it->p1], it->p1);
                        }
            }
        }

    for (int i = 1; i < (1 << K); ++i)
    {
        int nrB = 0, aux = i;
        while (aux)
            ++nrB, aux &= aux - 1;;

        aux = i;
        while (aux)
        {
            int last = aux & -aux, aux2 = i ^ last;
            Drum[i][Lg[last]] = oo;

            if (aux2 == 0)
                Drum[i][Lg[last]] = D[Lg[last]][0][1];

            while (aux2)
            {
                int last2 = aux2 & -aux2;

                if (D[Lg[last]][nrB - 1][I[Lg[last2]]] != oo)
                    Drum[i][Lg[last]] = min(Drum[i][Lg[last]], Drum[i ^ last][Lg[last2]] + nrB * D[Lg[last]][nrB - 1][I[Lg[last2]]]);

                aux2 &= aux2 - 1;
            }

            aux &= aux - 1;
        }
    }

    int result = oo;
    for (int i = 1; i <= K; ++i)
        result = min(result, Drum[(1 << K) - 1][i]);

    G << result;

    F.close();
    G.close();
}