Cod sursa(job #2812316)

Utilizator cristi_macoveiMacovei Cristian cristi_macovei Data 4 decembrie 2021 13:01:20
Problema Ubuntzei Scor 100
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 3.35 kb
#define d(x) std::cout << x << std::endl
#define dm(msg, x) std::cout << msg << x << std::endl

#define all(a) a.begin(), a.end()
#define range(a, l, r) a.begin() + l, a.begin() + r
#define aall(a, n) a + 1, a + 1 + n
#define arange(a, l, r) a + l, a + r
	
#define maxself(a, b) a = std::max(a, b);
#define minself(a, b) a = std::min(a, b);

#define inout(f) std::ifstream in((f) + (std::string) ".in");std::ofstream out((f) + (std::string) ".out")

#include <iostream>
#include <fstream>
#include <vector>
#include <queue>
#include <cstring>

const int NMAX = 2e3;
const int KMAX = 15;
const int INF = 1e9 + 7;

class QElem {
public:
  int node, dist;

  QElem() = default;

  QElem(int node, int dist):
    node(node), dist(dist) {};

  bool operator < (const QElem& other) const {
    return dist < other.dist;
  }

  bool operator > (const QElem& other) const {
    return dist > other.dist;
  }
};

class Edge {
public: 
  int node, cost;

  Edge() = default;

  Edge(int node, int cost):
    node(node), cost(cost) {};
};

int n, m;
std::vector<Edge> graph[1 + NMAX];
std::vector<Edge> compressedGraph[1 + NMAX];

int k;
std::vector<int> targets;

std::priority_queue<QElem, std::vector<QElem>, std::greater<QElem>> pq;
int dist[1 + KMAX + 1][1 + NMAX];

int hamilton[1 << (1 + KMAX)][1 + KMAX];

void dijkstra(int srcIndex) {
  int src = targets[srcIndex];

  dist[srcIndex][src] = 0;
  pq.emplace(src, 0);

  while (!pq.empty()) {
    auto front = pq.top();
    pq.pop();

    if (front.dist > dist[srcIndex][front.node])
      continue;

    for (auto& edge : graph[front.node]) {
      int newDist = front.dist + edge.cost;

      if (dist[srcIndex][edge.node] == -1 || dist[srcIndex][edge.node] > newDist) {
        dist[srcIndex][edge.node] = newDist;
        pq.emplace(edge.node, newDist);
      }
    }
  }
}

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

  in >> n >> m;
  
  in >> k;
  targets.resize(k + 2);
  targets[0] = 1;
  for (int i = 1; i <= k; ++i)
    in >> targets[i];
  targets[k + 1] = n;

  for (int i = 1; i <= m; ++i) {
    int x, y, z;
    in >> x >> y >> z;

    graph[x].emplace_back(y, z);
    graph[y].emplace_back(x, z);
  }

  memset(dist, -1, sizeof(dist));

  for (int i = 0; i <= k + 1; ++i)
    dijkstra(i);

  for (int i = 0; i <= k + 1; ++i) {
    for (int j = i + 1; j <= k + 1; ++j) {
      compressedGraph[i].emplace_back(j, dist[i][targets[j]]);
      compressedGraph[j].emplace_back(i, dist[j][targets[i]]);
    }
  }

  // hamilton
  for (int mask = 0; mask < (1 << (k + 1)); ++mask) {
    for (int last = 0; last < k + 1; ++last) {
      hamilton[mask][last] = INF;
    }
  }

  hamilton[1][0] = 0;

  for (int mask = 0; mask < (1 << (k + 1)); ++mask) {
    for (int last = 0; last < k + 1; ++last) {
      if (!(mask & (1 << last)))
        continue;

      int newMask = mask ^ (1 << last);
      for (auto& edge: compressedGraph[last]) {
        if (mask & (1 << edge.node)) {
          if (hamilton[newMask][edge.node] + edge.cost < hamilton[mask][last])
            hamilton[mask][last] = hamilton[newMask][edge.node] + edge.cost;
        }
      }
    }
  }

  int best = INF;
  for (int i = 0; i <= k; ++i)
    best = std::min(best, hamilton[(1 << (k + 1)) - 1][i] + dist[k + 1][targets[i]]);
  
  out << best << '\n';

  return 0;
}