Cod sursa(job #2386291)

Utilizator Alex_BubBuburuzan Alexandru Alex_Bub Data 22 martie 2019 14:48:45
Problema Ubuntzei Scor 10
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 2.73 kb
#include <fstream>
#include <cstring>
#include <vector>
#include <utility>

using namespace std;

ifstream fin("ubuntzei.in");
ofstream fout("ubuntzei.out");

const int ConfMax = (1 << 15), KMax = 15, NMax = 2000, oo = 2e9;

int N, M, K, DP[ConfMax + 5][KMax + 5], C[KMax + 5][KMax + 5], P[NMax + 5], D[NMax + 5], S;

///Cij - distanta minima de la nodul V[i] la nodul V[j]

vector < pair<int, int> > G[NMax + 5];

vector <int> V;

struct heap{int cod, val;} H[4 * NMax + 5];

void Up(int i)
{
    while(i > 1 && H[i].val < H[i / 2].val)
    {
        swap(P[H[i].cod], P[H[i / 2].cod]);
        swap(H[i], H[i / 2]);
    }
}

void Down(int i)
{
    int son = 1;

    while(son)
    {
        son = 0;

        if(2 * i <= S && H[i].val > H[2 * i].val)
            son = 2 * i;

        if(2 * i + 1 <= S && H[son].val > H[2 * i + 1].val)
            son = 2 * i + 1;

        if(son)
        {
            swap(P[H[i].cod], P[H[son].cod]);
            swap(H[i], H[son]);
            i = son;
        }
    }
}

void Delete(int i)
{
    swap(P[H[i].cod], P[H[S].cod]);
    swap(H[i], H[S]);

    S--; Up(i); Down(i);
}

void Update(int i, int V)
{
    H[i].val = V; Down(i);
}

void Dijkstra(int k)
{
    int Nod = V[k];

    for(int i = 1; i <= N; i++)
        D[i] = oo, P[i] = i, H[i].cod = i, H[i].val = oo;

    S = N; D[Nod] = 0; Update(P[Nod], 0);

    while(S)
    {
        int Nod = H[1].cod, Vecin, Cost; Delete(1);

        for(auto x : G[Nod])
        {
            Vecin = x.first, Cost = x.second;

            if(D[Nod] + Cost < D[Vecin])
            {
                D[Vecin] = D[Nod] + Cost;
                Update(P[Vecin], D[Vecin]);
            }
        }
    }
    for(int i = 0; i < K; i++)
        C[k][i] = D[V[i]];
}

void Read()
{
    fin >> N >> M >> K;

    V.push_back(1), V.push_back(N);

    for(int i = 1, x; i <= K; i++)
        fin >> x, V.push_back(x);

    K += 2;

    for(int i = 0, x, y, c; i < M; i++)
    {
        fin >> x >> y >> c;

        G[x].push_back({y, c});
        G[y].push_back({x, c});
    }
}

void Solve_and_Print()
{
    int Lim = (1 << K) - 1;

    for(int i = 1; i <= Lim; i++)
        for(int j = 0; j <= K; j++)
            DP[i][j] = oo;

    DP[1][0] = 0;

    for(int i = 1; i <= Lim; i++)
        for(int j = 0; j < K; j++)
            if(i & (1 << j))
            {
                for(int k = 0; k < K; k++)
                {
                    DP[i][j] = min(DP[i][j], DP[i - (1 << j)][k] + C[k][j]);
                }
            }
    fout << DP[Lim][1] << '\n';
}

int main()
{
    Read();

    for(int i = 0; i < K; i++) Dijkstra(i);

    Solve_and_Print();

    return 0;
}