Cod sursa(job #2297804)

Utilizator alexge50alexX AleX alexge50 Data 6 decembrie 2018 17:18:34
Problema Ubuntzei Scor 25
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 3.09 kb
/*
 *  Giving the Linus Torvalds Award to the Free Software Foundation
 *  is a bit like giving the Han Solo Award to the Rebel Alliance.
 *      - Richard M. Stallman
 */

#include <fstream>
#include <vector>
#include <queue>
#include <memory>

const int INF = 1 << 28;
const int MAX_K = 17;

struct Edge
{
    int from, to;
    int cost;
};

std::unique_ptr<std::vector<int>> dijkstra(const std::vector<std::vector<Edge>> &graph, int nNodes, int startNode)
{
    std::unique_ptr<std::vector<int>> result{new std::vector<int>};
    std::vector<int> &distances = *result;
    std::vector<bool> was;
    std::priority_queue<std::pair<int, int>, std::vector<std::pair<int, int>>, std::greater<std::pair<int, int>>> pq;

    distances.insert(distances.begin(), static_cast<unsigned long>(nNodes), INF);
    was.insert(was.begin(), static_cast<unsigned long>(nNodes), false);

    distances[startNode] = 0;
    pq.push({distances[startNode], startNode});
    while(!pq.empty())
    {
        while(!pq.empty() && was[pq.top().second])
            pq.pop();

        if(!pq.empty())
        {
            int x = pq.top().second;
            pq.pop();

            for(auto edge: graph[x])
            {
                if(distances[x] + edge.cost < distances[edge.to])
                {
                    distances[edge.to] = distances[x] + edge.cost;
                    pq.push({distances[edge.to], edge.to});
                }
            }
        }
    }

    return result;
}

int cost[MAX_K][MAX_K];
int d[1 << MAX_K][MAX_K];

int main()
{
    std::ifstream fin("ubuntzei.in");
    int n, m, k;
    std::vector<int> pointsOfInterest;
    std::vector<std::vector<Edge>> graph;

    fin >> n >> m >> k;

    pointsOfInterest.insert(pointsOfInterest.begin(), static_cast<unsigned long>(k + 2), {});
    pointsOfInterest[0] = 0;
    pointsOfInterest[k + 1] = n - 1;
    for(int i = 1; i <= k; i++)
        fin >> pointsOfInterest[i], pointsOfInterest[i]--;

    graph.insert(graph.begin(), static_cast<unsigned long>(n), {});
    for(int i = 0; i < m; i++)
    {
        int x, y, z;
        fin >> x >> y >> z;

        x--; y --;
        graph[x].push_back({x, y, z});
        graph[y].push_back({y, x, z});
    }

    for(int i = 0; i < k + 2; i++)
        for(int j = 0; j < k + 2; j++)
            cost[i][j] = i == j ? 0 : INF;

    for(int i = 0; i < pointsOfInterest.size(); i++)
    {
        auto d = dijkstra(graph, n, pointsOfInterest[i]);

        for(int j = 0; j < pointsOfInterest.size(); j++)
            cost[i][j] = (*d)[pointsOfInterest[j]];
    }

    int nn = k + 2;

    for(int i = 0; i < (1 << nn); i++)
        for(int j = 0; j < nn; j++)
            d[i][j] = INF;
    d[1][0] = 0;

    for(int i = 3; i < (1 << nn); i += 2)
        for(int j = 0; j < nn; j++)
            for(int k = 0; k < nn; k++)
                if(((1 << k) & i) != 0 && k != j)
                {
                    d[i][j] = std::min(d[i][j], d[i ^ (1 << j)][k] + cost[k][j]);
                }

    std::ofstream fout("ubuntzei.out");
    int r = INF;
    for(int i = 0; i < nn; i++)
        r = std::min(r, d[(1 << nn) - 1][i]);
    fout << r;

    return 0;
}