Cod sursa(job #3280012)

Utilizator BledeaAlexBledea Alexandru BledeaAlex Data 25 februarie 2025 10:46:10
Problema Ubuntzei Scor 100
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 2.97 kb
#include <bits/stdc++.h>

using namespace std;

const int N_MAX = 2005, M_MAX = 10005, K_MAX = 18, MASK_MAX = 1 << K_MAX, INF = 1 << 28;
int N, M, K;

int C[K_MAX];
int dist[K_MAX][K_MAX];

struct Edge
{
    int v, c;

    Edge(int _v, int _c) :
        v(_v), c(_c) { }

    inline bool operator> (const Edge& rhs) const
    {
        return c > rhs.c;
    }
};

vector<Edge> G[N_MAX];

void SetInput(string name)
{
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);

    (void)!freopen((name + ".in").c_str(), "r", stdin);
    (void)!freopen((name + ".out").c_str(), "w", stdout);
}

void ReadInput()
{
    cin >> N >> M >> K;
    K += 2; /// pentru nodul 1 si N

    C[1] = 1;
    C[K] = N;
    for(int i = 2, v; i < K; i++)
    {
        cin >> v;
        C[i] = v;
    }

    for(int i = 0, u, v, c; i < M; i++)
    {
        cin >> u >> v >> c;
        G[u].emplace_back(v, c);
        G[v].emplace_back(u, c);
    }
}

void Djikstra(int start, int dist[K_MAX])
{
    vector<int> crDist(N + 1, INF);

    crDist[start] = 0;

    priority_queue<Edge, vector<Edge>, greater<Edge> > PQ;

    PQ.emplace(start, 0);

    while(not PQ.empty())
    {
        auto [v, d] = PQ.top();
        PQ.pop();

        if(d > crDist[v])
            continue;

        for(auto& [u, c] : G[v])
            if(crDist[u] > d + c)
            {
                crDist[u] = d + c;
                PQ.emplace(u, crDist[u]);
            }
    }

    for(int i = 1; i <= K; i++)
        dist[i] = crDist[C[i]];
}

void Precomp()
{
    for(int i = 1; i <= K; i++)
        Djikstra(C[i], dist[i]);
}

struct MaskEdge
{
    int v, mask, c;

    MaskEdge(int _v, int _mask, int _c) :
        v(_v), mask(_mask), c(_c) { }

    inline bool operator> (const MaskEdge& rhs) const
    {
        return c > rhs.c;
    }
};

void MaskBellmanFord()
{
    int maxMask = (1 << K) - 1;

    vector<vector<int> > crDist(K + 1, vector<int>(maxMask + 1, INF));
    vector<bitset<MASK_MAX> > inQueue(K + 1, 0);

    queue<pair<int, int> > Q;

    crDist[1][1] = 0;
    Q.emplace(1, 1);
    inQueue[1][1] = 1;

    while(not Q.empty())
    {
        auto [v, mask] = Q.front();

        Q.pop();
        inQueue[v][mask] = 0;

        int d = crDist[v][mask];

        int newMask;
        for(int u = 1; u <= K; u++)
            if(u != v)
            {
                newMask = mask | (1 << (u-1));
                if(crDist[u][newMask] > d + dist[v][u])
                {
                    crDist[u][newMask] = d + dist[v][u];
                    if(not inQueue[u][newMask])
                    {
                        Q.emplace(u, newMask);
                        inQueue[u][newMask] = 1;
                    }
                }
            }
    }

    cout << crDist[K][maxMask] << '\n';
}

int main()
{
    SetInput("ubuntzei");

    ReadInput();
    Precomp();
    MaskBellmanFord();

    return 0;
}