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

#include <algorithm>
#include <cfloat>
#include <cmath>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <stack>
#include <stdio.h>
#include <string>
#include <time.h>
#include <vector>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define MOD 1000000007
#define EPS 0.000000001
using namespace std;

#define HUGE_NUM 99999999999999999
#define NUM 100001

enum Type {
  from_S,
  from_T,
  from_U,
  from_V,
};

struct Edge {
  Edge(int arg_to, ll arg_cost) {
    to = arg_to;
    cost = arg_cost;
  }
  int to;
  ll cost;
};

struct Info {
  Info(int arg_node_id, ll arg_sum_cost) {
    node_id = arg_node_id;
    sum_cost = arg_sum_cost;
  }
  bool operator<(const struct Info &arg) const {
    return sum_cost > arg.sum_cost;
  }

  int node_id;
  ll sum_cost;
};

struct Data {
  Data(int arg_node_id, ll arg_dist) {
    node_id = arg_node_id;
    dist = arg_dist;
  }
  bool operator<(const struct Data &arg) const { return dist < arg.dist; }

  int node_id;
  ll dist;
};

int N, M, S, T, U, V;
int start[4];
vector<Edge> G[NUM];
ll min_dist[NUM][4], min_dist_from_U[NUM];

void calc(Type type) {

  for (int i = 1; i <= N; i++) {
    min_dist[i][type] = HUGE_NUM;
  }

  min_dist[start[type]][type] = 0;

  priority_queue<Info> Q;
  Q.push(Info(start[type], 0));

  int next_node;
  ll next_cost;

  while (!Q.empty()) {
    if (Q.top().sum_cost > min_dist[Q.top().node_id][type]) {
      Q.pop();
    } else {

      for (int i = 0; i < G[Q.top().node_id].size(); i++) {
        next_node = G[Q.top().node_id][i].to;
        next_cost = Q.top().sum_cost + G[Q.top().node_id][i].cost;

        if (min_dist[next_node][type] > next_cost) {
          min_dist[next_node][type] = next_cost;
          Q.push(Info(next_node, next_cost));
        }
      }
      Q.pop();
    }
  }
}

int main() {

  scanf("%d %d", &N, &M);
  scanf("%d %d", &S, &T);
  scanf("%d %d", &U, &V);

  start[from_S] = S;
  start[from_T] = T;
  start[from_U] = U;
  start[from_V] = V;

  int from, to;
  ll cost;

  for (int loop = 0; loop < M; loop++) {
    scanf("%d %d %lld", &from, &to, &cost);
    G[from].push_back(Edge(to, cost));
    G[to].push_back(Edge(from, cost));
  }

  calc(from_S);
  calc(from_T);
  calc(from_U);
  calc(from_V);

  vector<Data> DATA;

  for (int i = 1; i <= N; i++) {
    DATA.push_back(Data(i, min_dist[i][from_S]));
  }
  sort(DATA.begin(), DATA.end());

  ll ans = min_dist[V][from_U];
  int node_id, adj_node;

  for (int i = 1; i <= N; i++)
    min_dist_from_U[i] = min_dist[i][from_U];

  for (int i = 0; i < DATA.size(); i++) {
    node_id = DATA[i].node_id;
    ans = min(ans, min_dist[node_id][from_U] + min_dist[node_id][from_V]);
    for (int k = 0; k < G[node_id].size(); k++) {
      adj_node = G[node_id][k].to;
      if (min_dist[node_id][from_S] + G[node_id][k].cost +
              min_dist[adj_node][from_T] !=
          min_dist[T][from_S])
        continue;
      min_dist[adj_node][from_U] =
          min(min_dist[adj_node][from_U], min_dist[node_id][from_U]);
    }
  }

  for (int i = 0; i < DATA.size(); i++) {
    node_id = DATA[i].node_id;
    ans = min(ans, min_dist[node_id][from_V] + min_dist_from_U[node_id]);
    for (int k = 0; k < G[node_id].size(); k++) {
      adj_node = G[node_id][k].to;
      if (min_dist[node_id][from_S] + G[node_id][k].cost +
              min_dist[adj_node][from_T] !=
          min_dist[T][from_S])
        continue;
      min_dist[adj_node][from_V] =
          min(min_dist[adj_node][from_V], min_dist[node_id][from_V]);
    }
  }

  printf("%lld\\n", ans);

  return 0;
}


Error: TLE

Fixed submission:

#include <algorithm>
#include <cfloat>
#include <cmath>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <stack>
#include <stdio.h>
#include <string>
#include <time.h>
#include <vector>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define MOD 1000000007
#define EPS 0.000000001
using namespace std;

#define HUGE_NUM 99999999999999999
#define NUM 100001

enum Type {
  from_S,
  from_T,
  from_U,
  from_V,
};

struct Edge {
  Edge(int arg_to, ll arg_cost) {
    to = arg_to;
    cost = arg_cost;
  }
  int to;
  ll cost;
};

struct Info {
  Info(int arg_node_id, ll arg_sum_cost) {
    node_id = arg_node_id;
    sum_cost = arg_sum_cost;
  }
  bool operator<(const struct Info &arg) const { // 総コストの昇順(PQ)
    return sum_cost > arg.sum_cost;
  }

  int node_id;
  ll sum_cost;
};

int N, M, S, T, U, V;
int start[4], goal[4];
vector<Edge> G[NUM];
ll min_dist[NUM][4];
map<int, ll> MAP;

void calc(Type type) {

  for (int i = 1; i <= N; i++) {
    min_dist[i][type] = HUGE_NUM;
  }

  min_dist[start[type]][type] = 0;

  priority_queue<Info> Q;
  Q.push(Info(start[type], 0));

  int next_node;
  ll next_cost;

  while (!Q.empty()) {
    if (Q.top().node_id == goal[type]) {
      Q.pop();
    } else if (Q.top().sum_cost > min_dist[Q.top().node_id][type]) {
      Q.pop();
    } else {

      for (int i = 0; i < G[Q.top().node_id].size(); i++) {
        next_node = G[Q.top().node_id][i].to;
        next_cost = Q.top().sum_cost + G[Q.top().node_id][i].cost;

        if (min_dist[next_node][type] > next_cost) {
          min_dist[next_node][type] = next_cost;
          Q.push(Info(next_node, next_cost));
        }
      }
      Q.pop();
    }
  }
}

bool is_shortest(int from, int to, ll cost) {

  // printf("from:%d to:%d cost:%lld\\n",from,to,cost);

  MAP.clear();

  priority_queue<Info> Q;

  MAP[from] = 0;
  Q.push(Info(from, 0));

  int next_node;
  ll next_cost;

  while (!Q.empty()) {

    if (Q.top().sum_cost > cost) {
      Q.pop();
      continue;
    }

    auto check = MAP.find(Q.top().node_id);
    if (check != MAP.end() && MAP[Q.top().node_id] < Q.top().sum_cost) {
      Q.pop();
      continue;
    }

    if (Q.top().node_id == to) {
      // printf("OK\\n");
      return true;
    } else {

      for (int i = 0; i < G[Q.top().node_id].size(); i++) {

        next_node = G[Q.top().node_id][i].to;
        next_cost = Q.top().sum_cost + G[Q.top().node_id][i].cost;

        if (next_cost > cost)
          continue;

        auto at = MAP.find(next_node);

        if (at == MAP.end()) {
          MAP[next_node] = next_cost;
          Q.push(Info(next_node, next_cost));
        } else {
          if (MAP[next_node] > next_cost) {
            MAP[next_node] = next_cost;
            Q.push(Info(next_node, next_cost));
          }
        }
      }

      Q.pop();
    }
  }

  // printf("駄目\\n");
  return false;
}

int main() {

  scanf("%d %d", &N, &M);
  scanf("%d %d", &S, &T);
  scanf("%d %d", &U, &V);

  start[from_S] = S;
  goal[from_S] = T;

  start[from_T] = T;
  goal[from_T] = S;

  start[from_U] = U;
  goal[from_U] = V;

  start[from_V] = V;
  goal[from_V] = U;

  int from, to;
  ll cost;

  for (int loop = 0; loop < M; loop++) {
    scanf("%d %d %lld", &from, &to, &cost);
    G[from].push_back(Edge(to, cost));
    G[to].push_back(Edge(from, cost));
  }

  calc(from_S);
  calc(from_T);
  calc(from_U);
  calc(from_V);

  vector<int> Group;
  for (int i = 1; i <= N; i++) {
    if (min_dist[i][from_S] + min_dist[i][from_T] ==
        min_dist[T][from_S]) { // 最短経路上の点をpush
      // printf("%dを通る\\n",i);
      Group.push_back(i);
    }
  }

  ll ans = min_dist[V][from_U]; // U→Vへ
  int near, longer;

  for (int i = 0; i < Group.size(); i++) {
    for (int k = 0; k < Group.size(); k++) {

      if (min_dist[Group[i]][from_S] > min_dist[Group[k]][from_S]) {
        near = Group[k];
        longer = Group[i];
      } else {
        near = Group[i];
        longer = Group[k];
      }

      if (!is_shortest(near, longer,
                       abs(min_dist[near][from_S] - min_dist[longer][from_S])))
        continue;

      ans = min(ans, min_dist[Group[i]][from_U] + min_dist[Group[k]][from_V]);
    }
  }

  printf("%lld\\n", ans);

  return 0;
}