Cod sursa(job #2982340)

Utilizator matei.tudoseMatei Tudose matei.tudose Data 19 februarie 2023 23:43:15
Problema Ubuntzei Scor 75
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 3.17 kb
#include <fstream>
#include <vector>
#include <cstring>
#include <queue>
using namespace std;

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

class muchie
{
public:
    int to, cost;
    bool operator<(const muchie &x) const
    {
        return cost > x.cost;
    }
};

// Variabile pentru Dijkstra
int n, m, nrPrieteni, drumMinim[18][2005], noduriPrieteni[20];
vector<muchie> G[2005];
priority_queue<muchie> minHeapMuchii;
// Variabile pentru lantul Hamiltonian
int hamilton[(1 << 18)][20];

void dijkstra(int indicePrieten)
{
    while (!minHeapMuchii.empty())
    {
        muchie curent = minHeapMuchii.top();
        minHeapMuchii.pop();
        if (curent.cost > drumMinim[indicePrieten][curent.to])
            continue;
        for (int i = 0; i < G[curent.to].size(); i++)
        {
            muchie vecin = G[curent.to][i], addToHeap;
            addToHeap.to = vecin.to;
            addToHeap.cost = curent.cost + vecin.cost;
            // Cost mai bun sau nu am setat un drum prin nodul respectiv
            if (addToHeap.cost < drumMinim[indicePrieten][vecin.to])
            {
                drumMinim[indicePrieten][vecin.to] = addToHeap.cost;
                minHeapMuchii.push(addToHeap);
            }
        }
    }
}

int main()
{
    fin >> n >> m >> nrPrieteni;
    for (int i = 1; i <= nrPrieteni; i++)
    {
        int nod;
        fin >> nod;
        noduriPrieteni[i] = nod;
    }
    // 0 -> start, 1 -> nrPrieteni avem noduri cu prieteni, iar (nrPrieteni + 1) -> finish
    noduriPrieteni[0] = 1;
    noduriPrieteni[nrPrieteni + 1] = n;
    nrPrieteni += 2;

    for (int i = 0; i < m; i++)
    {
        int from;
        muchie it;
        fin >> from >> it.to >> it.cost;
        G[from].push_back(it);
        swap(it.to, from);
        G[from].push_back(it);
    }

    memset(drumMinim, 0x3f3f3f3f, sizeof drumMinim);
    for (int i = 0; i < nrPrieteni + 2; i++)
    {
        int prieten = noduriPrieteni[i];
        muchie it;
        it.cost = 0;
        it.to = prieten;
        drumMinim[i][prieten] = 0;
        minHeapMuchii.push(it);
        dijkstra(i);
    }

    // Cautam lanutul Hamiltonian printre nodurile prietene
    memset(hamilton, 0x3f3f3f3f, sizeof hamilton);
    hamilton[1][0] = 0;

    for (int config = 1; config < (1 << nrPrieteni); config++)
    {
        for (int pozitieBit = 0; pozitieBit < nrPrieteni; pozitieBit++)
        {
            // Nodul curent este in configuratie
            if (config & (1 << pozitieBit))
            {
                for (int contorVecin = 0; contorVecin < nrPrieteni; contorVecin++)
                {
                    // Vecinul nu poate fi nodul in care deja suntem
                    if (contorVecin == pozitieBit)
                        continue;
                    // Vecinul nu este prezent in configuratie
                    if (!(config & (1 << contorVecin)))
                        hamilton[config + (1 << contorVecin)][contorVecin] = min(hamilton[config + (1 << contorVecin)][contorVecin], hamilton[config][pozitieBit] + drumMinim[pozitieBit][noduriPrieteni[contorVecin]]);
                }
            }
        }
    }

    fout << hamilton[(1 << nrPrieteni) - 1][nrPrieteni - 1] << "\n";
    return 0;
}