Cod sursa(job #2250243)

Utilizator SqueekDanielTodasca Daniel SqueekDaniel Data 30 septembrie 2018 13:22:55
Problema Gather Scor 0
Compilator cpp Status done
Runda Arhiva de probleme Marime 3.38 kb
#include <bits/stdc++.h>

#define MaxN 755
#define MaxK 16
#define inf  (ll)(1e9)
#define ll   long long

std::ifstream InFile("gather.in");
std::ofstream OutFile("gather.out");

ll ContainedInmate[MaxN],
    InmateCell[MaxK];
ll K;

inline ll BitCount(ll x) {
    if(x==0) return 0;
    return (x&1) + BitCount(x/2);
}

struct DijkstraStruct {
    ll Value;;
    ll Node;
    bool operator < (const DijkstraStruct &D) const {
        return Value > D.Value;
    }
};

template <ll NNodes>
struct GraphStruct {
    ll N;
    ll Capacity[NNodes][NNodes],
        EdgeLen[NNodes][NNodes];
    struct NodeStruct {
        std::list <ll> ADC;
    }   Node[NNodes];

    inline void AddEdge(ll x, ll y, ll Len, ll D) {
        Node[x].ADC.push_back(y);
        Node[y].ADC.push_back(x);
        EdgeLen[x][y] = EdgeLen[y][x] = Len;
        Capacity[x][y] = Capacity[y][x] = D;
    }

    ll Dist[MaxK][MaxK][NNodes];               // Dist[i][j][k] - distanta min de la nodul cu detinutul j la nodul k, folosing muchii cu capacitate minim i
    std::priority_queue <DijkstraStruct> DijkstraQueue;

    bool InQueue[NNodes];
    void Dijkstra(ll Source, ll MinCapacity, ll Inmate) {// MinCapacity - cati detinuti ducem
        ll *D = Dist[MinCapacity][Inmate];
        for (ll i=0; i<=NNodes; ++i)
            D[i+1] = inf, InQueue[i+1] = 0;

        D[Source] = 0;
        InQueue[Source] = 1;
        DijkstraQueue.push({0, Source});

        DijkstraStruct Top;
        while(!DijkstraQueue.empty()) {
            Top = DijkstraQueue.top();
            DijkstraQueue.pop();

            if(Top.Value > D[Top.Node]) continue;

            for (auto Vecin:Node[Top.Node].ADC) {
                if (D[Vecin] > D[Top.Node] + EdgeLen[Top.Node][Vecin] && Capacity[Top.Node][Vecin] >= MinCapacity) {
                    D[Vecin] = D[Top.Node] + EdgeLen[Top.Node][Vecin];

                    DijkstraQueue.push({D[Vecin], Vecin});
                }
            }
        }

        for (ll i=1; i<N; ++i)
            if(D[i+1] < inf)
                D[i+1] *= MinCapacity+1;
    }

    void BuildInmateGraph() {
        for (int j=0; j<=K+1; ++j)
            Dijkstra(0, j, 0);

        for (ll i=1, j; i<=K; ++i)
            for (j=0; j<=K+1; ++j)
                Dijkstra(InmateCell[i], j, i);
    }
};  GraphStruct <MaxN> Graph;

ll Dyn[1<<MaxK][MaxK];
void DP() {
    ll Lim = (1<<(K+1));
    for (ll i=0, j; i<Lim; ++i)
        for (j=0; j<=K; ++j)
            Dyn[i][j] = inf;

    Dyn[1][0] = 0;
    for (ll i=2, j, l, NBits; i<Lim; ++i) {
        NBits = BitCount(i)-2;
        for (j=0; j<=K; ++j)
            if (i&(1<<j))
                for (l=0; l<=K; ++l)
                    Dyn[i][j] = std::min(Dyn[i][j], Dyn[i^(1<<j)][l] + Graph.Dist[NBits][l][InmateCell[j]]);
    }
}

void Citire() {
    InFile >> K >> Graph.N;
    ll M; InFile >> M;

    for (ll i=0, x; i<K; ++i)
        InFile >> InmateCell[i+1],
        InmateCell[i+1]--;

    for (ll i=0, x, y, Len, D; i<M; ++i)
        InFile >> x >> y >> Len >> D,
        x--, y--,
        Graph.AddEdge(x, y, Len, D);
}
void Rezolvare() {
    Graph.BuildInmateGraph();
    DP();

    ll Rez = inf;
    for (ll i=0; i<=K; ++i)
        Rez = std::min(Rez, Dyn[(1<<(K+1))-1][i]);
    OutFile << Rez << '\n';
}


int main()
{
    Citire();
    Rezolvare();

    return 0;
}