Problem p00498 (C++)

Buggy submission (status: Runtime Error):
#include <algorithm>
#include <bitset>
#include <cassert>
#include <climits>
#include <cmath>
#include <complex>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iomanip>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <sstream>
#include <stack>
#include <string>
#include <valarray>
#include <vector>
using namespace std;

#define REP(i, n) for (int i = 0; i < (int)n; ++i)
#define FOR(i, c)                                                              \
  for (__typeof((c).begin()) i = (c).begin(); i != (c).end(); ++i)
#define ALL(c) (c).begin(), (c).end()
typedef long long ll;
typedef pair<int, int> pii;
const int INF = 1 << 29;
const double PI = acos(-1);
const double EPS = 1e-8;

vector<pii> g[100000];
int N, M, K, Q;

int dist[200000];
int f[100000];

void dijkstra() {
  REP(i, N) dist[i] = INF;
  priority_queue<pii> Q;
  REP(i, K) {
    Q.push(pii(0, f[i]));
    dist[f[i]] = 0;
  }
  while (!Q.empty()) {
    pii p = Q.top();
    Q.pop();
    int d = -p.first;
    int now = p.second;
    if (dist[now] < d)
      continue;
    FOR(it, g[now]) {
      int nd = d + it->second;
      if (dist[it->first] > nd) {
        dist[it->first] = nd;
        Q.push(pii(-nd, it->first));
      }
    }
  }
}

template <class T> struct UnionFind {
  vector<int> data;
  vector<T> val;
  UnionFind(int size) : data(size, -1), val(size) { REP(i, size) val[i] = i; }
  bool unionSet(int x, int y, T v) {
    x = root(x);
    y = root(y);
    if (x != y) {
      if (data[y] < data[x])
        swap(x, y);
      data[x] += data[y];
      data[y] = x;
      val[x] = v;
    }
    return x != y;
  }
  bool findSet(int x, int y) { return root(x) == root(y); }
  int root(int x) { return data[x] < 0 ? x : data[x] = root(data[x]); }
  int size(int x) { return -data[root(x)]; }
  T &value(int x) { return val[root(x)]; }
};

typedef pair<int, pii> P;
P edges[200000];

vector<int> tree[200000];

void spanningTree() {
  REP(i, 2 * N) tree[i].clear();
  int num = 0;
  REP(i, N)
  FOR(it, g[i]) if (i < it->first) edges[num++] =
      (P(min(dist[i], dist[it->first]), pii(i, it->first)));
  assert(num == M);
  sort(edges, edges + num, greater<P>());

  UnionFind<int> uf(N);
  int cnt = N;
  REP(i, num) {
    int a = edges[i].second.first;
    int b = edges[i].second.second;
    if (!uf.findSet(a, b)) {
      int x = uf.value(a);
      int y = uf.value(b);
      uf.unionSet(a, b, cnt);
      tree[cnt].push_back(x);
      tree[cnt].push_back(y);
      tree[x].push_back(cnt);
      tree[y].push_back(cnt);
      dist[cnt] = edges[i].first;
      cnt++;
    }
  }
  assert(cnt == 2 * N - 1);
}

const int MAX_N = 200000 * 2;
pii dat[MAX_N * 2 - 1];
int rmq_n;
void rmq_init(int *v, int size) {
  for (rmq_n = 1; rmq_n < size; rmq_n *= 2)
    ;
  REP(i, 2 * rmq_n - 1) dat[i] = pii(INF, -1);
  REP(i, size) { dat[rmq_n - 1 + i] = pii(v[i], i); }
  for (int i = rmq_n - 2; i >= 0; --i)
    dat[i] = min(dat[i * 2 + 1], dat[i * 2 + 2]);
}
pii query(int a, int b, int k, int l, int r) {
  if (r <= a || b <= l)
    return pii(INF, -1);
  if (a <= l && r <= b)
    return dat[k];
  return min(query(a, b, k * 2 + 1, l, (l + r) / 2),
             query(a, b, k * 2 + 2, (l + r) / 2, r));
}
int q(int a, int b) { return query(a, b, 0, 0, rmq_n).second; }

const int MAX_V = 200000;

int vs[MAX_V * 2 - 1];
int depth[MAX_V * 2 - 1];
int id[MAX_V];

void dfs(int v, int p, int d, int &k) {
  id[v] = k;
  vs[k] = v;
  depth[k++] = d;
  FOR(it, tree[v]) {
    if (*it != p) {
      dfs(*it, v, d + 1, k);
      vs[k] = v;
      depth[k++] = d;
    }
  }
}

void lca_init(int V, int root) {
  int k = 0;
  dfs(root, -1, 0, k);
  rmq_init(depth, V * 2 - 1);
}

int lca(int u, int v) {
  if (id[u] > id[v])
    swap(u, v);
  return vs[q(id[u], id[v] + 1)];
}

int main() {
  ios::sync_with_stdio(0);
  while (cin >> N >> M >> K >> Q) {
    REP(i, N) g[i].clear();
    REP(i, M) {
      int a, b, c;
      cin >> a >> b >> c;
      a--;
      b--;
      g[a].push_back(pii(b, c));
      g[b].push_back(pii(a, c));
    }
    REP(i, K) {
      cin >> f[i];
      f[i]--;
    }
    dijkstra();
    spanningTree();
    // REP(i,2*N-1) {
    //   cout << i << " :";
    //   FOR(it, tree[i]) {
    //     cout << " " << *it;
    //   }
    //   cout << endl;
    // }
    lca_init(2 * N - 1, 2 * N - 2);
    REP(i, Q) {
      int a, b;
      cin >> a >> b;
      a--;
      b--;
      cout << dist[lca(a, b)] << endl;
    }
  }
}

Fixed submission:
#include <algorithm>
#include <bitset>
#include <cassert>
#include <climits>
#include <cmath>
#include <complex>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iomanip>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <sstream>
#include <stack>
#include <string>
#include <valarray>
#include <vector>
using namespace std;

#define REP(i, n) for (int i = 0; i < (int)n; ++i)
#define FOR(i, c)                                                              \
  for (__typeof((c).begin()) i = (c).begin(); i != (c).end(); ++i)
#define ALL(c) (c).begin(), (c).end()
typedef long long ll;
typedef pair<int, int> pii;
const int INF = 1 << 29;
const double PI = acos(-1);
const double EPS = 1e-8;

vector<pii> g[100000];
int N, M, K, Q;

int dist[200000];
int f[100000];

void dijkstra() {
  REP(i, N) dist[i] = INF;
  priority_queue<pii> Q;
  REP(i, K) {
    Q.push(pii(0, f[i]));
    dist[f[i]] = 0;
  }
  while (!Q.empty()) {
    pii p = Q.top();
    Q.pop();
    int d = -p.first;
    int now = p.second;
    if (dist[now] < d)
      continue;
    FOR(it, g[now]) {
      int nd = d + it->second;
      if (dist[it->first] > nd) {
        dist[it->first] = nd;
        Q.push(pii(-nd, it->first));
      }
    }
  }
}

template <class T> struct UnionFind {
  vector<int> data;
  vector<T> val;
  UnionFind(int size) : data(size, -1), val(size) { REP(i, size) val[i] = i; }
  bool unionSet(int x, int y, T v) {
    x = root(x);
    y = root(y);
    if (x != y) {
      if (data[y] < data[x])
        swap(x, y);
      data[x] += data[y];
      data[y] = x;
      val[x] = v;
    }
    return x != y;
  }
  bool findSet(int x, int y) { return root(x) == root(y); }
  int root(int x) { return data[x] < 0 ? x : data[x] = root(data[x]); }
  int size(int x) { return -data[root(x)]; }
  T &value(int x) { return val[root(x)]; }
};

typedef pair<int, pii> P;
P edges[200000];

vector<int> tree[200000];

void spanningTree() {
  REP(i, 2 * N) tree[i].clear();
  int num = 0;
  REP(i, N)
  FOR(it, g[i]) if (i < it->first) edges[num++] =
      (P(min(dist[i], dist[it->first]), pii(i, it->first)));
  assert(num == M);
  sort(edges, edges + num, greater<P>());

  UnionFind<int> uf(N);
  int cnt = N;
  REP(i, num) {
    int a = edges[i].second.first;
    int b = edges[i].second.second;
    if (!uf.findSet(a, b)) {
      int x = uf.value(a);
      int y = uf.value(b);
      uf.unionSet(a, b, cnt);
      tree[cnt].push_back(x);
      tree[cnt].push_back(y);
      tree[x].push_back(cnt);
      tree[y].push_back(cnt);
      dist[cnt] = edges[i].first;
      cnt++;
    }
  }
  assert(cnt == 2 * N - 1);
}

const int MAX_N = 400000 * 2;
pii dat[MAX_N * 2 - 1];
int rmq_n;
void rmq_init(int *v, int size) {
  for (rmq_n = 1; rmq_n < size; rmq_n *= 2)
    ;
  REP(i, 2 * rmq_n - 1) dat[i] = pii(INF, -1);
  REP(i, size) { dat[rmq_n - 1 + i] = pii(v[i], i); }
  for (int i = rmq_n - 2; i >= 0; --i)
    dat[i] = min(dat[i * 2 + 1], dat[i * 2 + 2]);
}
pii query(int a, int b, int k, int l, int r) {
  if (r <= a || b <= l)
    return pii(INF, -1);
  if (a <= l && r <= b)
    return dat[k];
  return min(query(a, b, k * 2 + 1, l, (l + r) / 2),
             query(a, b, k * 2 + 2, (l + r) / 2, r));
}
int q(int a, int b) { return query(a, b, 0, 0, rmq_n).second; }

const int MAX_V = 200000;

int vs[MAX_V * 2 - 1];
int depth[MAX_V * 2 - 1];
int id[MAX_V];

void dfs(int v, int p, int d, int &k) {
  id[v] = k;
  vs[k] = v;
  depth[k++] = d;
  FOR(it, tree[v]) {
    if (*it != p) {
      dfs(*it, v, d + 1, k);
      vs[k] = v;
      depth[k++] = d;
    }
  }
}

void lca_init(int V, int root) {
  int k = 0;
  dfs(root, -1, 0, k);
  rmq_init(depth, V * 2 - 1);
}

int lca(int u, int v) {
  if (id[u] > id[v])
    swap(u, v);
  return vs[q(id[u], id[v] + 1)];
}

int main() {
  ios::sync_with_stdio(0);
  while (cin >> N >> M >> K >> Q) {
    REP(i, N) g[i].clear();
    REP(i, M) {
      int a, b, c;
      cin >> a >> b >> c;
      a--;
      b--;
      g[a].push_back(pii(b, c));
      g[b].push_back(pii(a, c));
    }
    REP(i, K) {
      cin >> f[i];
      f[i]--;
    }
    dijkstra();
    spanningTree();
    // REP(i,2*N-1) {
    //   cout << i << " :";
    //   FOR(it, tree[i]) {
    //     cout << " " << *it;
    //   }
    //   cout << endl;
    // }
    lca_init(2 * N - 1, 2 * N - 2);
    REP(i, Q) {
      int a, b;
      cin >> a >> b;
      a--;
      b--;
      cout << dist[lca(a, b)] << endl;
    }
  }
}