Cod sursa(job #2463327)

Utilizator PatrickCplusplusPatrick Kristian Ondreovici PatrickCplusplus Data 28 septembrie 2019 11:27:06
Problema Ubuntzei Scor 0
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 3.57 kb
#include <bits/stdc++.h>

using namespace std;

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

int n, m, k, orase[20], heap[2019], drum[2019][2019], p[2019], dp[(1 << 15)][20];
bool viz[2019];
vector <pair <int, int> > Muchii[2019];

void UpHeap(int poz, int *v)
{
    if (poz / 2 < 1)
        return;
    int nodfiu = heap[poz];
    int nodtata = heap[poz / 2];
    if (v[nodfiu] < v[nodtata])
    {
        swap(p[nodfiu], p[nodtata]);
        swap(heap[poz], heap[poz / 2]);
        UpHeap(poz / 2, v);
    }
}

void DownHeap(int poz, int *v)
{
    if (poz * 2 > heap[0])
        return;
    int nodtata = heap[poz];
    int nodfiu1 = heap[poz * 2];
    int nodfiu2 = heap[poz * 2 + 1];
    if (v[nodtata] > v[nodfiu1] || v[nodtata] > v[nodfiu2])
    {
        if (v[nodfiu1] <= v[nodfiu2])
        {
            swap(p[nodfiu1], p[nodtata]);
            swap(heap[poz], heap[poz * 2]);
            DownHeap(poz * 2, v);
        }
        else
        {
            swap(p[nodfiu2], p[nodtata]);
            swap(heap[poz], heap[poz * 2 + 1]);
            DownHeap(poz * 2 + 1, v);
        }
    }
}

void Adauga(int nod, int *v)
{
    viz[nod] = true;
    heap[++heap[0]] = nod;
    p[nod] = heap[0];
    UpHeap(nod, v);
}

void Sterge(int poz, int *v)
{
    viz[heap[poz]] = false;
    swap(heap[poz], heap[heap[0]]);
    heap[heap[0]] = n + 1;
    --heap[0];
    DownHeap(poz, v);
}

void Dijkstra(int x)
{
    heap[0] = 0;
    for (int i = 1; i <= n + 1; ++i)
    {
        heap[i] = n + 1;
        drum[x][i] = (1 << 30);
        viz[i] = false;
    }
    drum[x][x] = 0;
    Adauga(x, drum[x]);
    while (heap[0] > 0)
    {
        int nod = heap[1];
        Sterge(1, drum[x]);
        for (int j = 0; j < Muchii[nod].size(); ++j)
        {
            int vecin = Muchii[nod][j].first;
            int cost = Muchii[nod][j].second;
            if (drum[x][vecin] > drum[x][nod] + cost)
            {
                drum[x][vecin] = drum[x][nod] + cost;
                if (viz[vecin] == true)
                {
                    UpHeap(p[vecin], drum[x]);
                }
                else
                {
                    Adauga(vecin, drum[x]);
                }
            }
        }
    }
}

int main()
{
    fin >> n >> m >> k;
    for (int i = 1; i <= k; ++i)
        fin >> orase[i];
    for (int i = 1; i <= m; ++i)
    {
        int x, y, z;
        fin >> x >> y >> z;
        Muchii[x].push_back({y, z});
        Muchii[y].push_back({x, z});
    }
    Dijkstra(1);
    for (int i = 1; i <= k; ++i)
        Dijkstra(orase[i]);
    int stare = (1 << k);
    for (int i = 0; i < stare; ++i)
    {
        for (int j = 0; j < k; ++j)
        {
            dp[stare][j] = (1 << 30);
        }
    }
    for (int i = 0; i < k; ++i)
        dp[(1 << i)][i] = drum[1][orase[i + 1]];
    for (int i = 1; i < stare; ++i)
    {
        for (int j = 0; j < k; ++j)
        {
            if ((stare >> j) & 1 == 1)
            {
                for (int t = 0; t < k; ++t)
                {
                    if ((stare >> t) & 1 == 0)
                    {
                        dp[((1 << t) | stare)][t] = min(dp[((1 << t) | stare)][t], dp[stare][j] + drum[orase[j + 1]][orase[t + 1]]);
                    }
                }
            }
        }
    }
    int minim = (1 << 30);
    for (int i = 0; i < k; ++i)
        minim = min(minim, dp[(1 << k) - 1][i] + drum[orase[i + 1]][n]);
    fout << minim;
    fin.close();
    fout.close();
    return 0;
}