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

#include <bits/stdc++.h>
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 NUM 100000

struct Edge {
  Edge(int arg_from, int arg_to, int arg_dist) {
    from = arg_from;
    to = arg_to;
    dist = arg_dist;
    festival_dist = BIG_NUM;
  }
  bool operator<(const struct Edge &arg) const {
    return festival_dist > arg.festival_dist; // 祭りまでの最短距離の降順
  }
  int from, to, dist, festival_dist;
};

struct Info {
  Info(int arg_node_id, int arg_sum_dist) {
    node_id = arg_node_id;
    sum_dist = arg_sum_dist;
  }
  bool operator<(const struct Info &arg) const {
    return sum_dist > arg.sum_dist; // 総移動距離の昇順(PQ)
  }
  int node_id, sum_dist;
};

vector<Edge> EDGE, G[NUM];
vector<int> QUERY[NUM];
int min_dist[NUM];
int ans[NUM], boss[NUM];

int get_boss(int id) {
  if (id == boss[id])
    return id;
  else {
    return boss[id] = get_boss(boss[id]);
  }
}

void unite(int x, int y, int festival_dist) {

  int x_boss = get_boss(x);
  int y_boss = get_boss(y);

  if (x_boss == y_boss)
    return;

  // x_bossの方を大きくする
  if (QUERY[y_boss].size() > QUERY[x_boss].size())
    swap(x_boss, y_boss);

  bool FLG;

  // クエリ番号が出会うかどうか調べる
  for (int i = 0; i < QUERY[y_boss].size(); i++) {
    FLG = true;
    for (int k = 0; k < QUERY[x_boss].size(); k++) {
      if (QUERY[y_boss][i] == QUERY[x_boss][k]) { // ★SとTが出会った場合★
        ans[QUERY[y_boss][i]] = festival_dist;
        FLG = false;
        QUERY[x_boss].erase(QUERY[x_boss].begin() + k);
        break;
      }
    }
    if (FLG) {
      QUERY[x_boss].push_back(QUERY[y_boss][i]);
    }
  }

  boss[y_boss] = x_boss; // y_bossをx_bossに併合
}

int main() {

  int N, M, K, num_query;
  scanf("%d %d %d %d", &N, &M, &K, &num_query);

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

  int node_id;
  stack<int> S;

  for (int loop = 0; loop < K; loop++) {
    scanf("%d", &node_id);
    node_id--;
    S.push(node_id);
  }

  // クエリ情報を取得
  int start, goal;
  for (int loop = 0; loop < num_query; loop++) {
    scanf("%d %d", &start, &goal);
    start--;
    goal--;
    QUERY[start].push_back(loop); // ノードに、クエリ番号の集合を作る
    QUERY[goal].push_back(loop);
  }

  // 各ノードの、祭りノードまでの最短距離を求める
  for (int i = 0; i < N; i++)
    min_dist[i] = BIG_NUM;
  priority_queue<Info> Q;

  int next_node, next_cost;

  while (!S.empty()) {
    node_id = S.top();
    S.pop();

    min_dist[node_id] = 0;
    Q.push(Info(node_id, 0));

    while (!Q.empty()) {

      if (Q.top().sum_dist > min_dist[Q.top().node_id]) {

        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_dist + G[Q.top().node_id][i].dist;

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

  // エッジを、祭りノードとの距離の降順にsortする
  for (int i = 0; i < M; i++) {
    EDGE[i].festival_dist =
        min(min_dist[EDGE[i].from], min_dist[EDGE[i].to]); // 近い方の値を採用
  }
  sort(EDGE.begin(), EDGE.end());

  for (int i = 0; i < N; i++) {
    boss[i] = i;
  }

  for (int i = 0; i < M; i++) {
    unite(EDGE[i].from, EDGE[i].to, EDGE[i].festival_dist);
  }

  for (int i = 0; i < num_query; i++) {
    printf("%d\\n", ans[i]);
  }

  return 0;
}


Error: TLE

Fixed submission:

#include <bits/stdc++.h>
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 NUM 100000

struct Edge {
  Edge(int arg_from, int arg_to, int arg_dist) {
    from = arg_from;
    to = arg_to;
    dist = arg_dist;
    festival_dist = BIG_NUM;
  }
  bool operator<(const struct Edge &arg) const {
    return festival_dist > arg.festival_dist; // 祭りまでの最短距離の降順
  }
  int from, to, dist, festival_dist;
};

struct Info {
  Info(int arg_node_id, int arg_sum_dist) {
    node_id = arg_node_id;
    sum_dist = arg_sum_dist;
  }
  bool operator<(const struct Info &arg) const {
    return sum_dist > arg.sum_dist; // 総移動距離の昇順(PQ)
  }
  int node_id, sum_dist;
};

vector<Edge> EDGE, G[NUM];
vector<int> QUERY[NUM];
int min_dist[NUM];
int ans[NUM], boss[NUM];

int get_boss(int id) {
  if (id == boss[id])
    return id;
  else {
    return boss[id] = get_boss(boss[id]);
  }
}

void unite(int x, int y, int festival_dist) {

  int x_boss = get_boss(x);
  int y_boss = get_boss(y);

  if (x_boss == y_boss)
    return;

  // x_bossの方を大きくする
  if (QUERY[y_boss].size() > QUERY[x_boss].size())
    swap(x_boss, y_boss);

  bool FLG;
  vector<int> NEXT, DEL;

  // クエリ番号が出会うかどうか調べる
  for (int i = 0; i < QUERY[x_boss].size(); i++) {
    FLG = true;
    for (int k = 0; k < QUERY[y_boss].size(); k++) {
      if (QUERY[x_boss][i] == QUERY[y_boss][k]) { // ★SとTが出会った場合★
        ans[QUERY[x_boss][i]] = festival_dist;
        DEL.push_back(QUERY[x_boss][i]);
        FLG = false;
        break;
      }
    }
    if (FLG) {
      NEXT.push_back(QUERY[x_boss][i]);
    }
  }

  for (int i = 0; i < QUERY[y_boss].size(); i++) {
    FLG = true;
    for (int k = 0; k < DEL.size(); k++) {
      if (QUERY[y_boss][i] == DEL[k]) {
        FLG = false;
        break;
      }
    }
    if (!FLG)
      continue;
    QUERY[x_boss].push_back(QUERY[y_boss][i]);
  }

  boss[y_boss] = x_boss; // y_bossをx_bossに併合
}

int main() {

  int N, M, K, num_query;
  scanf("%d %d %d %d", &N, &M, &K, &num_query);

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

  int node_id;
  stack<int> S;

  for (int loop = 0; loop < K; loop++) {
    scanf("%d", &node_id);
    node_id--;
    S.push(node_id);
  }

  // クエリ情報を取得
  int start, goal;
  for (int loop = 0; loop < num_query; loop++) {
    scanf("%d %d", &start, &goal);
    start--;
    goal--;
    QUERY[start].push_back(loop); // ノードに、クエリ番号の集合を作る
    QUERY[goal].push_back(loop);
  }

  // 各ノードの、祭りノードまでの最短距離を求める
  for (int i = 0; i < N; i++)
    min_dist[i] = BIG_NUM;
  priority_queue<Info> Q;

  int next_node, next_cost;

  while (!S.empty()) {
    node_id = S.top();
    S.pop();

    min_dist[node_id] = 0;
    Q.push(Info(node_id, 0));

    while (!Q.empty()) {

      if (Q.top().sum_dist > min_dist[Q.top().node_id]) {

        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_dist + G[Q.top().node_id][i].dist;

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

  // エッジを、祭りノードとの距離の降順にsortする
  for (int i = 0; i < M; i++) {
    EDGE[i].festival_dist =
        min(min_dist[EDGE[i].from], min_dist[EDGE[i].to]); // 近い方の値を採用
  }
  sort(EDGE.begin(), EDGE.end());

  for (int i = 0; i < N; i++) {
    boss[i] = i;
  }

  for (int i = 0; i < M; i++) {
    unite(EDGE[i].from, EDGE[i].to, EDGE[i].festival_dist);
  }

  for (int i = 0; i < num_query; i++) {
    printf("%d\\n", ans[i]);
  }

  return 0;
}