Problem p01697 (C++) — buggy submission, verdict: Time Limit Exceeded

#include "bits/stdc++.h"
#include <unordered_map>
#include <unordered_set>
#pragma warning(disable : 4996)
using namespace std;
using ld = long double;
template <class T> using Table = vector<vector<T>>;

struct Edge {
  int from;
  int to;
  int cost;
  int time;
  int compa;
};

struct aa {
  int now;
  int time;
  int cost;
};
class Compare {
public:
  // aa?????????????????¶
  bool operator()(const aa &l, const aa &r) { return l.cost > r.cost; }
};
int main() {
  while (1) {

    int N, M, H, K;
    cin >> N >> M >> H >> K;
    if (!N)
      break;
    vector<vector<Edge>> edges(N);
    for (int i = 0; i < M; ++i) {
      int a, b, c, h, r;
      cin >> a >> b >> c >> h >> r;
      a--;
      b--;
      r--;
      edges[a].push_back(Edge{a, b, c, h, r});
      edges[b].push_back(Edge{b, a, c, h, r});
    }
    int S, T;
    cin >> S >> T;
    S--;
    T--;
    int P;
    cin >> P;
    vector<int> passcost;
    vector<vector<bool>> frees(P, vector<bool>(K, false));
    for (int p = 0; p < P; ++p) {
      int l, d;
      cin >> l >> d;
      passcost.push_back(d);
      for (int j = 0; j < l; ++j) {
        int k;
        cin >> k;
        k--;
        frees[p][k] = true;
      }
    }
    vector<int> dp(1 << K, 1e8);
    dp[0] = 0;
    for (int i = 0; i < (1 << K); ++i) {
      bitset<8> bs(i);
      for (int p = 0; p < passcost.size(); ++p) {
        bitset<8> newbs(bs);
        for (int k = 0; k < K; ++k) {
          if (frees[p][k])
            newbs[k] = true;
        }
        dp[newbs.to_ulong()] = min(dp[newbs.to_ulong()], dp[i] + passcost[p]);
      }
    }
    int ans = 1e8;

    for (int i = 0; i < (1 << K); ++i) {
      vector<vector<int>> memo(N, vector<int>(H + 1, 1e8));
      bitset<8> bs(i);
      vector<bool> free(K);
      int money = dp[i];
      priority_queue<aa, vector<aa>, Compare> que;
      que.push(aa{S, 0, 0});
      memo[S][0] = 0;

      while (!que.empty()) {
        aa atop(que.top());
        que.pop();
        const int nowplace = atop.now;
        const int nowtime = atop.time;
        const int nowcost = atop.cost;
        for (auto e : edges[nowplace]) {
          const int nextplace = e.to;
          const int nextcost = bs[e.compa] ? nowcost : nowcost + e.cost;
          const int nexttime = nowtime + e.time;
          if (nexttime > H)
            continue;
          else if (nextcost < memo[nextplace][nexttime]) {
            memo[nextplace][nexttime] = nextcost;
            que.push(aa{nextplace, nexttime, nextcost});
          }
        }
      }
      for (int h = 0; h <= H; ++h) {
        if (memo[T][h] < 9e7) {
          ans = min(ans, money + memo[T][h]);
        }
      }
    }
    if (ans > 9e7)
      ans = -1;
    cout << ans << endl;
  }

  return 0;
}

Error: TLE

Fixed submission:

#include <algorithm>
#include <array>
#include <assert.h>
#include <bitset>
#include <complex>
#include <cstdlib>
#include <functional>
#include <iomanip>
#include <iostream>
#include <limits>
#include <map>
#include <math.h>
#include <numeric>
#include <queue>
#include <set>
#include <stack>
#include <stdio.h>
#include <stdio.h>
#include <string.h>
#include <string>
#include <vector>
using namespace std;

struct edge {
  int f;
  int t;
  int h;
  int c;
  int r;
};

struct aa {
  int now;
  int ntime;
  int ncost;
};
class Compare {
public:
  // keiroが昇順に並ぶ
  bool operator()(const aa &l, const aa &r) { return l.ncost > r.ncost; }
};

int dp[12][12][100001];
int main() {
  /*int n, d, x; cin >> n >> d >> x;
  vector<vector<int>>costs(d, vector<int>(n));
  for (int i = 0; i < d; ++i) {
  for (int j = 0; j < n; ++j) {
  int p; cin >> p;
  costs[i][j] = p;
  }
  }
  memset(dp, 0, sizeof(dp));
  dp[10][10][x] = x;
  const int aaa = 100000;

  for (int j = 0; j <=aaa; ++j) {
  for (int k = 0; k <= 10; ++k) {
  for (int i = 0; i <= 10; ++i) {
  dp[k][i][j] = j;
  }
  }
  }

  for (int from = d-1; from >= 0; --from) {
  for (int money = 0; money <= aaa; ++money) {
  for (int to = from + 1; to < d; ++to) {
  for (int kabu = 0; kabu < n; ++kabu) {
  if (money >= costs[from][kabu]) {
  dp[from][to][money] = max(dp[from][to][money], dp[from][to][money -
  costs[from][kabu]]  + costs[to][kabu]);
  }
  }
  dp[from][to + 1][money] = max(dp[from][to][money], dp[from][to + 1][money]);

  for (int keiyu = from + 1; keiyu < to; ++keiyu) {
  int nextmoney = dp[from][keiyu][money];
  if (nextmoney > aaa)continue;
  dp[from][to][money] = max(dp[from][to][money], dp[keiyu][to][nextmoney]);
  }
  }

  }

  const int nfrom = from;
  for (int money = 0; money <= aaa; ++money) {
  for (int to = nfrom + 2; to <= d; ++to) {

  for (int keiyu = nfrom+1; keiyu < to; ++keiyu) {
  int nextmoney = dp[nfrom][keiyu][money];
  if (nextmoney > aaa)continue;
  dp[nfrom][to][money] = max(dp[nfrom][to][money], dp[keiyu][to][nextmoney]);
  }
  }
  }
  if (from) {
  for (int money = 0; money <= aaa; ++money) {
  for (int to = from + 1; to <= d; ++to) {

  for (int kabu = 0; kabu < n; ++kabu) {
  dp[from - 1][to][money] = max(dp[from][to][money], dp[from - 1][to][money]);
  }
  }
  }
  }
  }
  cout << dp[0][n][x] << endl;
  return 0;*/

  while (1) {

    int N, M, H, K;
    cin >> N >> M >> H >> K;
    if (!N)
      break;
    vector<vector<edge>> edges(N);
    for (int i = 0; i < M; ++i) {
      int a, b, c, h, r;
      cin >> a >> b >> c >> h >> r;
      r--;
      a--;
      b--;
      edges[a].push_back({a, b, h, c, r});
      edges[b].push_back({b, a, h, c, r});
    }
    int S, T, P;
    cin >> S >> T >> P;
    S--;
    T--;
    vector<int> places;
    vector<vector<bool>> Passs(P, vector<bool>(K));
    for (int i = 0; i < P; ++i) {
      int l, d;
      cin >> l >> d;
      vector<bool> frees(K);
      for (int j = 0; j < l; ++j) {
        int k;
        cin >> k;
        k--;
        frees[k] = true;
      }
      Passs[i] = frees;
      places.push_back(d);
    }

    vector<bool> afrees(K);
    vector<int> pasm(1 << K, 99999999);
    {
      int pasmoney = 0;
      for (int i = 0; i < 1 << P; ++i) {
        vector<bool> afrees(K);
        int pasmoney = 0;
        for (int j = 0; j < P; ++j) {
          if ((1 << j) & i) {

            for (int n = 0; n < K; ++n) {
              if (Passs[j][n]) {

                afrees[n] = true;
              }
            }

            pasmoney += places[j];
          }
        }
        int a = 0;
        for (int n = 0; n < K; ++n) {
          if (afrees[n])
            a ^= 1 << n;
        }
        if (pasm[a] > pasmoney) {
          pasm[a] = pasmoney;
        }
      }
    }
    int minmoney = 99999999;
    for (int i = 0; i < 1 << K; ++i) {
      vector<bool> afrees(K);
      int pasmoney = pasm[i];
      if (pasmoney == 99999999)
        continue;

      for (int j = 0; j < K; ++j) {
        if (i & (1 << j)) {
          afrees[j] = true;
        }
      }
      vector<vector<int>> mincosts(N, vector<int>(H + 1, 99999999));
      mincosts[S][0] = 0;
      priority_queue<aa, vector<aa>, Compare> que;
      que.push(aa{S, 0, 0});
      while (!que.empty()) {
        const aa atop(que.top());
        que.pop();
        if (atop.ncost > mincosts[atop.now][atop.ntime])
          continue;
        for (auto i : edges[atop.now]) {
          if (atop.ntime + i.h > H)
            continue;
          const int acost = afrees[i.r] ? 0 : i.c;
          if (atop.ncost + acost < mincosts[i.t][atop.ntime + i.h]) {
            mincosts[i.t][atop.ntime + i.h] = atop.ncost + acost;
            que.push(aa{i.t, atop.ntime + i.h, atop.ncost + acost});
          }
        }
      }
      int amin = 99999999;
      for (int i = 0; i <= H; ++i) {
        amin = min(mincosts[T][i], amin);
      }
      minmoney = min(minmoney, amin + pasmoney);
    }
    if (minmoney == 99999999) {
      cout << -1 << endl;
    } else {
      cout << minmoney << endl;
    }
  }
  return 0;
}