Cod sursa(job #2026544)

Utilizator MoodyFaresFares Mohamad MoodyFares Data 24 septembrie 2017 16:32:00
Problema Ubuntzei Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.15 kb
#include <cstdio>
#include <queue>
#include <cstring>
#include <vector>
#include <climits>

const int MAX_K = 15;
const int MAX_N = 2000;

struct Edge {
  int u;
  int cost;

  bool operator <(const Edge &other) const {
    return this->cost > other.cost;
  }
};

int c[5 + MAX_K];
int distMin[5 + MAX_N][5 + MAX_N];
bool viz[5 + MAX_N];
int costMin[5 + 1 << MAX_K][MAX_K];

std::vector<Edge> g[5 + MAX_K];

void dijkstra(int node) {
  memset(viz, false, sizeof(viz));
  std::priority_queue<Edge> pq;
  pq.push({node, 0});
  while (!pq.empty()) {
    Edge top = pq.top();
    pq.pop();
    int u = top.u;
    if (!viz[u]) {
      viz[u] = true;
      distMin[node][u] = top.cost;
      for (auto e : g[u]) {
        if (!viz[e.u]) {
          pq.push({e.u, top.cost + e.cost});
        }
      }
    }
  }
}

void preCalc(int N) {
  for (int i = 0; i <= N; i++) {
    dijkstra(c[i]);
  }
}

int main() {
  freopen ("ubuntzei.in", "r", stdin);
  freopen ("ubuntzei.out", "w", stdout);

  int N, M, K;
  scanf("%d%d%d", &N, &M, &K);
  for (int i = 1; i <= K; i++) {
    scanf("%d", &c[i]);
  }
  c[0] = 1;
  c[K + 1] = N;
  for (int i = 1; i <= M; i++) {
    int u, v, cost;
    scanf("%d%d%d", &u, &v, &cost);
    g[u].push_back({v, cost});
    g[v].push_back({u, cost});
  }
  preCalc(K + 1);
  if (K == 0) {
    printf("%d\n", distMin[1][N]);
    return 0;
  }
  int lim = 1 << K;
  for (int i = 1; i < lim; i++) {
    for (int j = 1; j <= K; j++) {
      costMin[i][j] = INT_MAX;
    }
  }
  for (int i = 1; i <= K; i++) {
    costMin[1 << (i - 1)][i] = distMin[1][c[i]];
  }
  for (int orase = 1; orase < lim; orase++) {
    for (int i = 1; i <= K; i++) {
      if (orase & (1 << (i - 1))) {
        for (int j = 1; j <= K; j++) {
          if (i != j && orase & (1 << (j - 1))) {
            costMin[orase][i] = std::min(costMin[orase][i], costMin[orase ^ (1 << (i - 1))][j] + distMin[c[j]][c[i]]);
          }
        }
      }
    }
  }
  int ans = INT_MAX;
  for (int i = 1; i <= K; i++) {
    ans = std::min(ans, costMin[lim - 1][i] + distMin[c[i]][N]);
  }
  printf("%d\n", ans);
  return 0;
}