Cod sursa(job #2538801)

Utilizator MiricaMateiMirica Matei MiricaMatei Data 5 februarie 2020 10:02:49
Problema Gather Scor 20
Compilator cpp-64 Status done
Runda simulare_miri Marime 2.29 kb
#include <bits/stdc++.h>

using namespace std;

const int MAXN = 750;
const int MAXK = 15;
const int MAXM = 1250;

struct Edge {
  int u;
  long long c, d;
  bool operator <(const Edge& other) const {
    return c < other.c;
  }
};

struct Node {
  int node;
  long long c;
  bool operator <(const Node& other) const {
    return c > other.c;
  }
};

vector<Edge>G[MAXN + 5];
int det[MAXK + 5];
long long dist[MAXK + 5][MAXK + 5][MAXK + 5];
long long dd[MAXN + 5];
long long dp[(1 << MAXK) + 5][MAXK + 5];

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

  int n, m, k;
  scanf("%d%d%d", &k, &n, &m);
  for (int i = 1; i <= k; ++i)
    scanf("%d", &det[i]);
  for (int i = 1; i <= m; ++i) {
    int u, v;
    long long c, d;
    scanf("%d%d", &u, &v);
    scanf("%lld%lld", &d, &c);
    G[u].push_back({v, c, d});
    G[v].push_back({u, c, d});
  }
  for (int i = 1; i <= n; ++i)
    sort(G[i].begin(), G[i].end());
  det[0] = 1;
  for (int cat = 0; cat <= k; ++cat) {
    for (int d = 0; d <= k; ++d) {
      memset(dd, -1, sizeof(dd));
      priority_queue<Node>pq;
      pq.push({det[d], 0});
      while (!pq.empty()) {
        Node aux = pq.top();
        pq.pop();
        if (dd[aux.node] != -1)
          continue;
        dd[aux.node] = aux.c;
        for (auto it:G[aux.node]) {
          if (it.c < cat)
            break;
          if (dd[it.u] == -1 || 1LL * it.d * (cat + 1) + aux.c <= (1LL << 32))
            pq.push({it.u, 1LL * it.d * (cat + 1) + aux.c});
        }
      }
      for (int x = 0; x <= k; ++x)
        dist[cat][d][x] = dd[det[x]];
    }
  }

  memset(dp, -1, sizeof(dp));
  dp[0][0] = 0;
  k++;
  for (int s = 0; s < (1 << k); ++s) {
    int nb = 0;
    for (int i = 0; i < k; ++i)
      if (s & (1 << i))
        nb++;
    for (int i = 0; i < k; ++i)
      if (dp[s][i] != -1) {
        for (int j = 1; j < k; ++j) {
          if (s & (1 << j))
            continue;
          if (dp[s ^ (1 << j)][j] == -1)
            dp[s ^ (1 << j)][j] = dp[s][i] + dist[nb][i][j];
        }
      }
  }
  long long ans = (1LL << 60);
  for (int i = 1; i <= k; ++i)
    if (dp[(1 << k) - 2][i] != -1)
      ans = min(ans, dp[(1 << k) - 2][i]);
  printf("%lld\n", ans);

  return 0;
}