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

#include <bits/stdc++.h>

using namespace std;

#define fst(t) std::get<0>(t)
#define snd(t) std::get<1>(t)
#define thd(t) std::get<2>(t)

using ll = long long;
using P = std::tuple<int, int>;
using P3 = std::tuple<int, int, int>;

const int dx[8] = {-1, 1, 0, 0, -1, -1, 1, 1},
          dy[8] = {0, 0, -1, 1, -1, 1, -1, 1};

template <int n> struct UnionFind {
  UnionFind() {
    for (int i = 0; i < n; i++) {
      par[i] = i;
      rank[i] = 0;
    }
  }
  int find(int x) {
    if (x == par[x])
      return x;
    return find(par[x]);
  }
  bool same(int x, int y) { return find(x) == find(y); }
  void unite(int x, int y, int v) {
    x = find(x);
    y = find(y);
    if (x == y) {
      return;
    }

    if (rank[x] > rank[y]) {
      par[y] = x;
      value[y] = v;
    } else {
      par[x] = y;
      value[x] = v;
      if (rank[x] == rank[y]) {
        rank[y]++;
      }
    }
  }
  void addHeight() {
    memset(height, -1, sizeof(height));
    for (int i = 0; i < n; ++i) {
      _addHeight(i);
    }
  }
  int _addHeight(int v) {
    if (height[v] != -1) {
      return height[v];
    }

    if (v == par[v]) {
      return height[v] = 0;
    } else {
      return height[v] = _addHeight(par[v]) + 1;
    }
  }
  void climb(int &v, int &mn) {
    mn = min(mn, value[v]);
    v = par[v];
  }
  int lca(int u, int v) {
    if (height[u] > height[v]) {
      swap(u, v);
    }

    int mn_u = 1001001001, mn_v = 1001001001;
    while (height[v] > height[u]) {
      climb(v, mn_v);
    }

    while (u != v) {
      climb(u, mn_u);
      climb(v, mn_v);
    }

    return min(mn_u, mn_v);
  }

  int rank[n], par[n], value[n], height[n];
};

int N, M, K, Q;

vector<P> G[100100];
vector<P3> E;
std::priority_queue<P, std::vector<P>, std::greater<P>> pq;
int dist[100100];
UnionFind<100100> uf;

template <typename T, typename U, int N>
void dijkstra(std::vector<T> (&graph)[N], U (&dist)[N]) {
  while (!pq.empty()) {
    int u;
    U d;
    std::tie(d, u) = pq.top();
    pq.pop();

    if (dist[u] < d) {
      continue;
    }

    for (const auto &p : graph[u]) {
      int v;
      U c;
      std::tie(v, c) = p;
      if (dist[v] > d + c) {
        dist[v] = d + c;
        pq.emplace(dist[v], v);
      }
    }
  }
}

int main() {
  std::cin.tie(nullptr);
  std::ios::sync_with_stdio(false);

  std::cin >> N >> M >> K >> Q;

  for (int i = 0; i < M; ++i) {
    int a, b, c;
    std::cin >> a >> b >> c;

    G[a].emplace_back(b, c);
    G[b].emplace_back(a, c);
  }

  std::fill(dist, dist + 100100, std::numeric_limits<int>::max() / 2);

  for (int i = 0; i < K; ++i) {
    int v;
    std::cin >> v;

    dist[v] = 0;
    pq.emplace(0, v);
  }

  dijkstra(G, dist);

  for (int i = 1; i <= N; ++i) {
    for (auto &p : G[i]) {
      int j;
      tie(j, ignore) = p;

      E.emplace_back(min(dist[i], dist[j]), i, j);
    }
  }

  sort(E.rbegin(), E.rend());

  for (auto &p : E) {
    int m, u, v;
    tie(m, u, v) = p;

    uf.unite(u, v, m);
  }

  uf.addHeight();

  for (int i = 0; i < Q; ++i) {
    int u, v;
    std::cin >> u >> v;

    std::cout << uf.lca(u, v) << std::endl;
  }
}

Error: TLE

Fixed submission:

#include <algorithm>
#include <cmath>
#include <cstdio>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <stack>
#include <vector>

#define FOR(i, a, b) for (int i = (a); i < (b); i++)
#define REP(i, j) FOR(i, 0, j)
#define mp std::make_pair

const int INF = 1 << 24;
const int dx[8] = {0, 0, 1, -1, 1, 1, -1, -1},
          dy[8] = {1, -1, 0, 0, 1, -1, 1, -1};

typedef unsigned long long ull;
typedef std::pair<int, int> P;

struct Edge {
  int to, cost;
  Edge(int _to, int _cost) : to(_to), cost(_cost) {}
};

int N, M, K, Q;
int d[100000], d2[100000], used[100000];
std::vector<Edge> G[100000], H[100000];
std::vector<int> F;

void dijkstra() {
  std::fill(used, used + N, 0);
  std::fill(d, d + N, INF);

  std::priority_queue<P, std::vector<P>, std::greater<P>> q;
  REP(i, K) {
    d[F[i]] = 0;
    q.push(mp(0, F[i]));
  }

  while (!q.empty()) {
    P p = q.top();
    q.pop();
    int c = p.first, u = p.second;

    if (c > d[u]) {
      continue;
    }
    used[u] = 1;

    REP(i, G[u].size()) {
      Edge e = G[u][i];
      if (!used[e.to] && d[e.to] > c + e.cost) {
        d[e.to] = c + e.cost;
        q.push(mp(d[e.to], e.to));
      }
    }
  }
}

int dijkstra2(int s, int t) {
  std::fill(used, used + N, 0);
  std::fill(d2, d2 + N, -INF);

  std::priority_queue<P> q;
  d2[s] = d[s];
  q.push(mp(d[s], s));

  while (!q.empty()) {
    P p = q.top();
    q.pop();
    int m = p.first, u = p.second;

    if (d2[u] > m) {
      continue;
    }
    used[u] = 1;

    REP(i, G[u].size()) {
      int v = G[u][i].to;

      if (d2[v] < std::min(m, d[v])) {
        d2[v] = std::min(m, d[v]);
        q.push(mp(d2[v], v));
      }
    }
  }

  return d2[t];
}

int main() {
  std::cin >> N >> M >> K >> Q;

  REP(i, M) {
    int from, to, cost;
    std::cin >> from >> to >> cost;
    from--;
    to--;

    G[from].push_back(Edge(to, cost));
    G[to].push_back(Edge(from, cost));
  }

  REP(i, K) {
    int fes;
    std::cin >> fes;
    fes--;

    F.push_back(fes);
  }

  dijkstra();

  REP(i, Q) {
    int from, to;
    std::cin >> from >> to;
    from--;
    to--;

    std::cout << dijkstra2(from, to) << std::endl;
  }

  // REP(i, N){
  //     printf("%d: %d\\n", i+1, d[i]);
  // }
}