Cod sursa(job #2027431)

Utilizator MiricaMateiMirica Matei MiricaMatei Data 26 septembrie 2017 08:54:38
Problema Ubuntzei Scor 80
Compilator cpp Status done
Runda Arhiva de probleme Marime 1.98 kb
#include <cstdio>
#include <vector>
#include <queue>
#include <cstring>

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

struct Edge{
  int nod, cost;
  bool operator <(const Edge& other) const {
    return cost > other.cost;
  }
};

int oras[1 + MAX_K];
int dist[1 + MAX_N+2][1 + MAX_N + 2];
int dMin[1 + MAX_N];
bool viz[1 + MAX_N];
int dp[1 << MAX_K][1 + MAX_K];
std::vector<Edge>G[1 + MAX_N];

void distMin(int nod, int n, int k) {
  memset(dMin, 0, sizeof(dMin));
  memset(viz, 0, sizeof(viz));
  std::priority_queue<Edge>pq;
  pq.push({nod, 0});
  while (!pq.empty()) {
    Edge aux = pq.top();
    pq.pop();
    if(!viz[aux.nod]) {
      dMin[aux.nod] = aux.cost;
    } else {
      continue;
    }
    viz[aux.nod] = true;
    for (auto it:G[aux.nod])
      if (!viz[it.nod])
        pq.push({it.nod, dMin[aux.nod] + it.cost});
  }

  for (int i = 1; i<= n; ++i)
    dist[nod][i] = dMin[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", &oras[i]);

  for (int i=1; i <= m; ++i) {
    int u, v, c;
    scanf("%d%d%d", &u, &v, &c);
    G[u].push_back({v,c});
    G[v].push_back({u,c});
  }

  distMin(1, n, k);
  for (int i = 1; i <= k; ++i)
    distMin(oras[i], n, k);
  distMin(n, n, k);

  int ns = 1 << k;
  for (int i = 1; i < ns; ++i)
    for (int j = 1; j <= k; ++j)
      dp[i][j] = 20000000;
  for (int i = 0; i < k; ++i)
    dp[1 << i][i + 1] = dist[1][oras[i + 1]];
  for (int i = 1; i < ns; ++i) {
    for (int j = 0; j < k; ++j) {
      if(i & (1 << j) && i != 1 << j) {
        for (int p = 1; p <= k; ++p)
          dp[i][j + 1] = std::min(dp[i][j + 1], dp[i ^ (1 << j)][p] + dist[oras[p]][oras[j + 1]]);
      }
    }
  }

  int ans = (1LL << 31) - 1;
  for(int i = 1; i <= k; i++)
    ans = std::min(ans, dp[ns - 1][i] + dist[oras[i]][n]);

  printf("%d", ans);

  return 0;
}