Cod sursa(job #2610262)

Utilizator calinfloreaCalin Florea calinflorea Data 4 mai 2020 17:49:42
Problema Ubuntzei Scor 95
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 3.05 kb
#include <bits/stdc++.h>
#define oo (1 << 30)
#define DimMax 2006

using namespace std;

typedef int Atom;

struct Pereche{
    Atom cost, nod;
};

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

int a[DimMax], drum[DimMax], dist[17][17];
vector <pair <int, int> > L[DimMax];
Pereche Q[DimMax];
Atom P;
int n, m, K;
int dp[17][1 << 17];

void Insert (Pereche Q[], int &P, Pereche x)
{
    Q[++P] = x;
    int fiu = P, parinte = P / 2;

    while (parinte >= 1 && Q[parinte].cost > Q[fiu].cost)
    {
        std :: swap (Q[parinte], Q[fiu]);
        fiu = parinte;
        parinte /= 2;
    }
}

Atom Remove (Pereche Q[], int &P)
{
    int parinte = 1, fiu = 2;
    Atom ret_val;

    if (P == 0)
        return -1;

    ret_val = Q[1].nod;
    std :: swap (Q[1], Q[P]);
    P--;

    while (fiu <= P)
    {
        if (fiu + 1 <= P && Q[fiu].cost > Q[fiu + 1].cost)
            fiu++;
        if (Q[fiu].cost < Q[parinte].cost)
        {
            std :: swap (Q[parinte], Q[fiu]);
            parinte = fiu;
            fiu *= 2;
        }
        else
            fiu = P + 1;
    }

    return ret_val;
}


void Citire ()
{
    int x, y, c;
    fin >> n >> m >> K;

    for (int i = 1; i <= K; i++)
        fin >> a[i];
    a[0] = 1;
    K++;
    a[K] = n;
    for (int i = 1; i <= m; i++)
    {
        fin >> x >> y >> c;

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

void Dijkstra (int M)
{
    int i, cost, nod;

    Insert(Q, P, {0, M});
    for (int i = 1; i <= n; i++)
        drum[i] = oo;
    drum[M] = 0;

    while (P)
    {
        i = Remove(Q, P);
        for (int j = 0; j < L[i].size(); j++)
        {
            nod = L[i][j].first;
            cost = L[i][j].second;

            if (drum[nod] > drum[i] + cost)
            {
                drum[nod] = drum[i] + cost;
                Insert (Q, P, {drum[nod], nod});
            }
        }
    }
}

void Construieste ()
{
    for (int i = 0; i <= K; i++)
    {
        Dijkstra(a[i]);

        for (int j = 0; j <= K; j++)
            dist[i][j] = drum[a[j]];
    }
}

void Initialiazare ()
{
    for (int i = 0; i <= K; i++)
        for (int j = 1; j <= (1 << K) - 1; j++)
            dp[i][j] = oo;

    for(int i = 0; i <= K; i++)
        for(int j = 0; j <= K; j++)
            dist[i][j] = oo;
}

void Dinamica ()
{
    dp[0][1] = 0;
    int ans = oo;

    for (int i = 1; i <= (1 << K) - 1; i++)
        for (int j = 0; j <= K; j++)
            if ((i & (1 << j)) != 0)
                for (int p = 0; p <= K; p++)
                    if ((i & (1 << p)) == 0)
                        dp[p][i | (1 << p)] = min (dp[p][i | (1 << p)],
                                                  dp[j][i] + dist[j][p]);


    for (int i = 0; i <= K; i++)
        ans = min (ans, dp[i][(1 << K) - 1] + dist[i][K]);

    fout << ans << "\n";
}

int main()
{
    Citire();
    Initialiazare();
    Construieste();
    Dinamica();

    return 0;
}