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

#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <map>
#include <queue>
#include <stack>
#include <string>
#include <vector>
#define inf 0x3f3f3f3f
#define Inf 0x3FFFFFFFFFFFFFFFLL
#define eps 1e-9
#define pi acos(-1.0)
using namespace std;
typedef long long ll;
const int maxn = 55;
const int maxm = 1024;
struct Node {
  int d, u1, u2, state;
  Node() {}
  Node(int d, int u1, int u2, int state) : d(d), u1(u1), u2(u2), state(state) {}
  bool operator<(const Node &a) const { return d > a.d; }
};
vector<pair<int, int>> Go[maxn];
vector<pair<int, int>> Back[maxn];
int h[maxn], msk[maxn], cnt[maxm], val[maxn];
int d[maxn][maxn][maxm];
void Init(int n) {
  memset(msk, 0, sizeof(msk));
  memset(cnt, 0, sizeof(cnt));
  for (int i = 0; i <= n; ++i) {
    Go[i].clear();
    Back[i].clear();
  }
}
int solve(int n) {
  priority_queue<Node> q;
  memset(d, 0x3f, sizeof(d));
  d[1][1][1] = 0;
  q.push(Node(0, 1, 1, 1));
  Node node;
  int u1, u2, st;
  while (!q.empty()) {
    node = q.top();
    q.pop();
    u1 = node.u1;
    u2 = node.u2;
    st = node.state;
    if (d[u1][u2][st] < node.d)
      continue;
    if (h[u1] <= h[u2]) {
      for (int i = 0; i < (int)Go[u1].size(); i++) {
        int v = Go[u1][i].first;
        int nowst = 1 << msk[v], cost = node.d + Go[u1][i].second;
        if (h[v] > h[u2]) {
          nowst = 1 << msk[u2];
          if (h[u1] == h[u2])
            nowst |= st;
        } else if (h[v] == h[u2])
          nowst |= (1 << msk[u2]);
        if (h[u1] == h[v])
          nowst |= st;
        if (!(h[v] == h[u1] && (st >> msk[v] & 1)) && v != u2)
          cost += val[v];
        if (d[v][u2][nowst] > cost) {
          d[v][u2][nowst] = cost;
          q.push(Node(cost, v, u2, nowst));
        }
      }
    } else {
      for (int i = 0; i < (int)Back[u2].size(); ++i) {
        int v = Back[u2][i].first;
        int nowst = 1 << msk[v], cost = node.d + Back[u2][i].second;
        if (h[v] > h[u1]) {
          nowst = 1 << msk[u1];
          if (h[u1] == h[u2])
            nowst |= st;
        } else if (h[v] == h[u1])
          nowst |= (1 << msk[u1]);
        if (h[u2] == h[v])
          nowst |= st;
        if (!(h[v] == h[u2] && (st >> msk[v] & 1)) && v != u1)
          cost += val[v];
        if (d[u1][v][nowst] > cost) {
          d[u1][v][nowst] = cost;
          q.push(Node(cost, u1, v, nowst));
        }
      }
    }
  }
  int ans = inf;
  for (int i = 0; i < maxm; ++i)
    ans = min(ans, d[n][n][i]);
  return ans == inf ? -1 : ans;
}
int main() {
  // freopen("in.txt","r",stdin);
  // freopen("out.txt","w",stdout);
  int n, m;
  while (~scanf("%d%d", &n, &m)) {
    if (n == 0 && m == 0)
      break;
    Init(n);
    for (int i = 2; i < n; ++i) {
      scanf("%d%d", &val[i], &h[i]);
      msk[i] = cnt[h[i]]++;
    }
    h[1] = 0;
    h[n] = 1000;
    val[1] = val[n] = 0;
    msk[1] = cnt[h[1]]++;
    msk[n] = cnt[h[n]]++;
    int u, v, w;
    for (int i = 0; i < m; ++i) {
      scanf("%d%d%d", &u, &v, &w);
      if (h[u] <= h[v])
        Go[u].push_back(make_pair(v, w));
      if (h[u] >= h[v])
        Back[v].push_back(make_pair(u, w));
    }
    int ans = solve(n);
    printf("%d\\n", ans);
  }
  return 0;
}

Error: TLE

Fixed submission:

#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <queue>
using namespace std;
const int maxn = 60;
const int maxm = 4010;
const int inf = 0x3f3f3f3f;
int d[maxn], e[maxn];

struct Edge {
  int u, v, w, next;
  Edge() {}
  Edge(int t_u, int t_v, int t_w, int t_next) : u(t_u), v(t_v), w(t_w) {}
} edges[maxm];

int head[maxn], edge_sum;

void init_grapth() {
  edge_sum = 0;
  memset(head, -1, sizeof(head));
}

void addEdge(int u, int v, int w) {
  edges[edge_sum].u = u;
  edges[edge_sum].v = v;
  edges[edge_sum].w = w;
  edges[edge_sum].next = head[u];
  head[u] = edge_sum++;
}

int n, m;
bool used[maxn];
int pre[maxn];
int ans, ans_cnt;
bool visit[maxn];
int dis[maxn];
bool inq[maxn];

void spfa(int s) {
  memset(dis, inf, sizeof(dis));
  memset(inq, false, sizeof(inq));
  queue<int> Q;
  Q.push(s);
  dis[s] = 0;
  inq[s] = true;
  while (!Q.empty()) {
    int u = Q.front();
    Q.pop();
    inq[u] = false;
    for (int i = head[u]; i != -1; i = edges[i].next) {
      int v = edges[i].v;
      if (!visit[v]) {
        if (e[v] <= e[u] && dis[v] > dis[u] + edges[i].w + d[v]) {
          dis[v] = dis[u] + edges[i].w + d[v];
          if (!inq[v]) {
            Q.push(v);
            inq[v] = true;
          }
        }
      } else {
        if (e[v] <= e[u] && dis[v] > dis[u] + edges[i].w) {
          dis[v] = dis[u] + edges[i].w;
          if (!inq[v]) {
            Q.push(v);
            inq[v] = true;
          }
        }
      }
    }
  }
  return;
}

void dfs(int u, int p, int sum) {
  pre[u] = p;
  if (u == n) {
    ans_cnt++;
    memset(visit, false, sizeof(visit));
    int i = n;
    while (i != -1) {
      visit[i] = true;
      i = pre[i];
    }
    spfa(n);
    // printf("Test: %d %d\\n", sum, dis[1]);
    ans = min(ans, sum + dis[1]);
    return;
  }
  for (int i = head[u]; i != -1; i = edges[i].next) {
    int v = edges[i].v;
    if (!used[v] && e[v] >= e[u]) {
      used[v] = true;
      dfs(v, u, sum + edges[i].w + d[v]);
      used[v] = false;
    }
  }
  return;
}

int main() {

  // freopen("aa.in", "r", stdin);

  int u, v, w;
  while (scanf("%d %d", &n, &m) && n + m) {
    init_grapth();
    d[1] = 0;
    e[1] = 0;
    d[n] = 0;
    e[n] = 1000;
    for (int i = 2; i < n; ++i) {
      scanf("%d %d", &d[i], &e[i]);
    }
    for (int i = 1; i <= m; ++i) {
      scanf("%d %d %d", &u, &v, &w);
      addEdge(u, v, w);
    }
    memset(used, false, sizeof(used));
    memset(pre, -1, sizeof(pre));
    ans = inf;
    ans_cnt = 0;
    used[1] = true;
    dfs(1, -1, 0);
    if (ans_cnt == 0) {
      printf("-1\\n");
    } else {
      printf("%d\\n", ans);
    }
  }
  return 0;
}