Cod sursa(job #583627)

Utilizator darrenRares Buhai darren Data 21 aprilie 2011 14:36:40
Problema Gather Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 3.12 kb
#include <fstream>
#include <algorithm>
#include <vector>
#include <set>

using namespace std;

class trio
{
    public:
        int p1, p2, p3;

        trio();
        trio(int _p1, int _p2, int _p3)
        {
            p1 = _p1;
            p2 = _p2;
            p3 = _p3;
        }
};

typedef vector<trio> VT;
#define push_trio(define1, define2, define3) push_back(trio(define1, define2, define3))
#define insert_pair(define1, define2) insert(make_pair(define1, define2))

const int INF = 0x3f3f3f3f;

int N, M, K;
int I[16], minC[1 << 15][16], D[16][16][755];
int Log[1 << 15];
VT V[755];
set<pair<int, int> > S;

int main()
{
    ifstream fin("gather.in");
    ofstream fout("gather.out");

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

    fin >> K >> N >> M;
    for (int i = 1; i <= K; ++i)
        fin >> I[i];
    for (int i = 1, nod1, nod2, maxp, cost; i <= M; ++i)
    {
        fin >> nod1 >> nod2 >> cost >> maxp;
        V[nod1].push_trio(nod2, cost, maxp);
        V[nod2].push_trio(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] = INF;
            for (VT::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<int, int> now = *S.begin();
                S.erase(S.begin());

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

                for (VT::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;
            minC[i][Log[last]] = INF;

            if (aux2 == 0)
                minC[i][Log[last]] = D[Log[last]][0][1];

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

                if (D[Log[last]][nrB - 1][I[Log[last2]]] != INF)
                    minC[i][Log[last]] = min(minC[i][Log[last]], minC[i ^ last][Log[last2]] + nrB * D[Log[last]][nrB - 1][I[Log[last2]]]);

                aux2 &= aux2 - 1;
            }

            aux &= aux - 1;
        }
    }

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

    fout << result;

    fin.close();
    fout.close();
}