Cod sursa(job #961057)

Utilizator Stefex09Stefan Teodorescu Stefex09 Data 11 iunie 2013 16:38:13
Problema Gather Scor 30
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.44 kb
#include <iostream>
#include <fstream>
#include <vector>
#include <queue>
#include <cstring>

using namespace std;

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

const int MAXN = 755;
const int MAXK = 16;
const int INF = 0x3f3f3f3f;

struct triple
{
    int x, y, z;
};

int N;
vector <triple> Graf[MAXN];
int V[MAXK];
int A[MAXK][1 << MAXK], D[MAXK][MAXK][MAXN];
//A[i][j] = costul minim de a ajunge in nodul j, cu detinutii marcati cu 1 in reprezentarea binara a lui i
//D[i][j][k] = costul minim de a ajunge in nodul k, plecand din i si trecand prin muchii cu capacitatea >= j

priority_queue < pair < int, int> > Q;

void Dijkstra (int S, int lim, int Best[])
{
    int nod, d;

    for (nod = 0; nod <= N; nod ++)
        Best[nod] = INF;
    Best[S] = 0;
    Q.push (make_pair (0, S));

    while (!Q.empty ()){
        nod = Q.top ().second;
        d = -Q.top ().first;
        Q.pop ();

        if (Best[nod] < d)
            continue;

        for (auto it : Graf[nod]){
            if (it.z < lim)
                continue;

            if (Best[nod] + it.y < Best[it.x]){
                Best[it.x] = Best[nod] + it.y;
                Q.push (make_pair (-Best[it.x], it.x));
            }
        }
    }

    for (int i = 1; i <= N; i ++)
        Best[i] *= (lim + 1);
}

inline int nrbiti (int X)
{
    int ret = 0;

    while (X) ret ++, X &= X - 1;

    return ret;
}

int main()
{
    int M, K, i, j, k, nod1, nod2, cap, lung, now;

    in >> K >> N >> M;
    for (i = 1; i <= K; i ++)
        in >> V[i], -- V[i];

    while (M --){
        in >> nod1 >> nod2 >> lung >> cap;
        -- nod1, -- nod2;
        Graf[nod1].push_back ({nod2, lung, cap});
        Graf[nod2].push_back ({nod1, lung, cap});
    }

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

    memset (A, 0x3f, sizeof (A));
    A[1][0] = 0;

    for (i = 2; i < (1 << (K + 1)); i ++){
        now = nrbiti (i) - 2;

        for (j = 0; j <= K; j ++)
            if (i & (1 << j))
                for (k = 0; k <= K; k ++)
                    if (A[i ^ (1 << j)][k] != INF && D[k][now][V[j]] != INF)
                       A[i][j] = min (A[i][j], A[i ^ (1 << j)][k] + D[k][now][V[j]]);
    }

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

    out << Ans;

    return 0;
}