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

#include <algorithm>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <deque>
#include <iostream>
#include <list>
#include <map>
#include <queue>
#include <set>
#include <vector>

#define MAX(x, y) ((x > y) ? x : y)
#define min(x, y) ((x < y) ? x : y)
typedef long long ll;

using namespace std;

struct edge {
  int a, b, l, c;
  bool operator<(edge p) const { return (c < p.c); }
};
struct edge2 {
  int to, cost;
  edge2(int a, int b) {
    to = a;
    cost = b;
  }
  bool operator<(edge2 q) const { return (to < q.to); }
};
struct edge3 {
  int to, cost;
};
struct P {
  int min, v;
  P(int a, int b) { min = a, v = b; }
  bool operator<(P p) const { return (min > p.min); }
};

// Dijkstra
edge e[200005], e2[100005];
int fest[100005], cost[100005];
int vis[100005], dis[100005];
int n, en;
vector<edge2> G[100005];
priority_queue<P> que;
void dijkstra(int x) {
  int i, v;

  while (!que.empty()) {
    P p = que.top();
    que.pop();
    v = p.v;
    if (dis[v] < p.min)
      continue;
    for (i = 0; i < G[v].size(); i++) {
      edge2 e = G[v][i];
      if (dis[e.to] > dis[v] + e.cost) {
        dis[e.to] = dis[v] + e.cost;
        que.push(P(dis[e.to], e.to));
      }
    }
  }
  for (i = 1; i <= n; i++) {
    // printf("%2d %d\\n",i,dis[i]);
    // cost[i]=min(cost[i],dis[i]);
    cost[i] = dis[i];
  }
}

// Union-Find
int f[100005];
void init(int n) {
  for (int i = 1; i <= n; i++)
    f[i] = i;
  return;
}
int find(int x) {
  if (f[x] != x)
    f[x] = find(f[x]);
  return f[x];
}
void unite(int x, int y) {
  int p = find(x), q = find(y);
  f[p] = q;
  return;
}

// LCA
int depth[100005];
edge3 parents[20][100005];
int dfs(int v, int p, int d) {
  parents[0][v].to = p;
  // parents[0][v].cost=min(cost[v],(p==-1)?(1000000000):cost[p]);
  if (p == -1)
    parents[0][v].cost = cost[v];
  else
    parents[0][v].cost = min(cost[v], cost[p]);
  depth[v] = d;
  for (int i = 0; i < G[v].size(); i++) {
    edge2 ee = G[v][i];
    if (ee.to != p)
      dfs(ee.to, v, d + 1);
  }
}
void init2(int root) {
  dfs(root, -1, 0);
  for (int k = 0; k < 18; k++) {
    for (int v = 1; v <= n; v++) {
      if (parents[k][v].to < 0)
        parents[k + 1][v].to = -1;
      else {
        parents[k + 1][v].to = parents[k][parents[k][v].to].to;
        parents[k + 1][v].cost =
            min(parents[k][v].cost, parents[k][parents[k][v].to].cost);
      }
    }
  }
}
int lca(int a, int b) {
  int c, k, res;
  res = min(cost[a], cost[b]);
  if (depth[a] > depth[b])
    c = a, a = b, b = c;
  for (k = 0; k < 18; k++) {
    if (((depth[b] - depth[a]) >> k & 1)) {
      res = min(res, parents[k][b].cost);
      b = parents[k][b].to;
    }
  }
  if (a == b)
    return min(res, cost[a]);
  for (k = 17; k >= 0; k--) {
    if (parents[k][a].to != parents[k][b].to) {
      res = min(res, min(parents[k][a].cost, parents[k][b].cost));
      a = parents[k][a].to;
      b = parents[k][b].to;
    }
  }
  return min(res, parents[0][a].cost);
}
int main() {
  int i, j, k, m, K, q, s, t;
  priority_queue<edge> que2;

  scanf("%d%d%d%d", &n, &m, &K, &q);
  for (i = 0; i < m; i++) {
    scanf("%d%d%d", &e[i].a, &e[i].b, &e[i].l);
    G[e[i].a].push_back(edge2(e[i].b, e[i].l));
    G[e[i].b].push_back(edge2(e[i].a, e[i].l));
  }
  // Dijkstra
  fill(cost, cost + n + 1, 1000000000);
  fill(dis, dis + n + 1, 1000000000);
  for (i = 0; i < K; i++) {
    scanf("%d", &fest[i]);
    dis[fest[i]] = 0;
    que.push(P(0, fest[i]));
  }
  dijkstra(fest[0]);

  for (i = 1; i <= n; i++) {
    // printf("%2d %d\\n",i,cost[i]);
    G[i].clear();
  }
  // CreateTree
  init(n);
  en = 0;
  for (i = 0; i < m; i++) {
    e[i].c = min(cost[e[i].a], cost[e[i].b]);
    que2.push(e[i]);
  }
  while (!que2.empty()) {
    edge ee = que2.top();
    que2.pop();
    if (find(ee.a) != find(ee.b)) {
      unite(ee.a, ee.b);
      e2[en++] = ee;
      G[ee.a].push_back(edge2(ee.b, ee.c));
      G[ee.b].push_back(edge2(ee.a, ee.c));
    }
  }

  // LCA
  init2(1);
  /*
  printf("en:%d\\n",en);
  for(i=0;i<en;i++)printf("%d %d\\n",e2[i].a,e2[i].b);
  for(i=1;i<=n;i++){
          printf("%d(dep:%d):",i,depth[i]);
          for(j=0;j<3;j++)printf("%2d(%2d)
  ",parents[j][i].to,parents[j][i].cost); printf("\\n");
  }
  */

  while (q--) {
    scanf("%d%d", &s, &t);
    // printf("%d %d ->lca %d\\n",s,t,lca(s,t));
    printf("%d\\n", lca(s, t));
  }

  return 0;
}

Error: TLE

Fixed submission:

#include <algorithm>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <deque>
#include <iostream>
#include <list>
#include <map>
#include <queue>
#include <set>
#include <vector>

#define MAX(x, y) ((x > y) ? x : y)
#define min(x, y) ((x < y) ? x : y)
typedef long long ll;

using namespace std;

struct edge {
  int a, b, l, c;
  bool operator<(edge p) const { return (c < p.c); }
};
struct edge2 {
  int to, cost;
  edge2(int a, int b) {
    to = a;
    cost = b;
  }
  bool operator<(edge2 q) const { return (to < q.to); }
};
struct edge3 {
  int to, cost;
};
struct P {
  int min, v;
  P(int a, int b) { min = a, v = b; }
  bool operator<(P p) const { return (min > p.min); }
};

// Dijkstra
edge e[200005], e2[100005];
int fest[100005], cost[100005];
int vis[100005], dis[100005];
int n, en;
vector<edge2> G[100005];
void dijkstra(int x) {
  int i, v;
  priority_queue<P> que;
  fill(dis, dis + n + 1, 1000000000);
  dis[x] = 0;
  que.push(P(0, x));
  while (!que.empty()) {
    P p = que.top();
    que.pop();
    v = p.v;
    if (dis[v] < p.min)
      continue;
    for (i = 0; i < G[v].size(); i++) {
      edge2 e = G[v][i];
      if (dis[e.to] > dis[v] + e.cost) {
        dis[e.to] = dis[v] + e.cost;
        que.push(P(dis[e.to], e.to));
      }
    }
  }
  for (i = 1; i <= n; i++) {
    // printf("%2d %d\\n",i,dis[i]);
    cost[i] = min(cost[i], dis[i]);
  }
}

// Union-Find
int f[100005];
void init(int n) {
  for (int i = 1; i <= n; i++)
    f[i] = i;
  return;
}
int find(int x) {
  if (f[x] != x)
    f[x] = find(f[x]);
  return f[x];
}
void unite(int x, int y) {
  int p = find(x), q = find(y);
  f[p] = q;
  return;
}

// LCA
int depth[100005];
edge3 parents[20][100005];
int dfs(int v, int p, int d) {
  parents[0][v].to = p;
  // parents[0][v].cost=min(cost[v],(p==-1)?(1000000000):cost[p]);
  if (p == -1)
    parents[0][v].cost = cost[v];
  else
    parents[0][v].cost = min(cost[v], cost[p]);
  depth[v] = d;
  for (int i = 0; i < G[v].size(); i++) {
    edge2 ee = G[v][i];
    if (ee.to != p)
      dfs(ee.to, v, d + 1);
  }
}
void init2(int root) {
  dfs(root, -1, 0);
  for (int k = 0; k < 18; k++) {
    for (int v = 1; v <= n; v++) {
      if (parents[k][v].to < 0)
        parents[k + 1][v].to = -1;
      else {
        parents[k + 1][v].to = parents[k][parents[k][v].to].to;
        parents[k + 1][v].cost =
            min(parents[k][v].cost, parents[k][parents[k][v].to].cost);
      }
    }
  }
}
int lca(int a, int b) {
  int c, k, res;
  res = min(cost[a], cost[b]);
  if (depth[a] > depth[b])
    c = a, a = b, b = c;
  for (k = 0; k < 18; k++) {
    if (((depth[b] - depth[a]) >> k & 1)) {
      res = min(res, parents[k][b].cost);
      b = parents[k][b].to;
    }
  }
  if (a == b)
    return min(res, cost[a]);
  for (k = 17; k >= 0; k--) {
    if (parents[k][a].to != parents[k][b].to) {
      res = min(res, min(parents[k][a].cost, parents[k][b].cost));
      a = parents[k][a].to;
      b = parents[k][b].to;
    }
  }
  return min(res, parents[0][a].cost);
}
int main() {
  int i, j, k, m, K, q, s, t;
  priority_queue<edge> que2;

  scanf("%d%d%d%d", &n, &m, &K, &q);
  for (i = 0; i < m; i++) {
    scanf("%d%d%d", &e[i].a, &e[i].b, &e[i].l);
    G[e[i].a].push_back(edge2(e[i].b, e[i].l));
    G[e[i].b].push_back(edge2(e[i].a, e[i].l));
  }
  // Dijkstra
  fill(cost, cost + n + 1, 1000000000);
  for (i = 0; i < K; i++) {
    scanf("%d", &fest[i]);
    dijkstra(fest[i]);
  }
  for (i = 1; i <= n; i++) {
    // printf("%2d %d\\n",i,cost[i]);
    G[i].clear();
  }
  // CreateTree
  init(n);
  en = 0;
  for (i = 0; i < m; i++) {
    e[i].c = min(cost[e[i].a], cost[e[i].b]);
    que2.push(e[i]);
  }
  while (!que2.empty()) {
    edge ee = que2.top();
    que2.pop();
    if (find(ee.a) != find(ee.b)) {
      unite(ee.a, ee.b);
      e2[en++] = ee;
      G[ee.a].push_back(edge2(ee.b, ee.c));
      G[ee.b].push_back(edge2(ee.a, ee.c));
    }
  }

  // LCA
  init2(1);
  /*
  printf("en:%d\\n",en);
  for(i=0;i<en;i++)printf("%d %d\\n",e2[i].a,e2[i].b);
  for(i=1;i<=n;i++){
          printf("%d(dep:%d):",i,depth[i]);
          for(j=0;j<3;j++)printf("%2d(%2d)
  ",parents[j][i].to,parents[j][i].cost); printf("\\n");
  }
  */

  while (q--) {
    scanf("%d%d", &s, &t);
    // printf("%d %d ->lca %d\\n",s,t,lca(s,t));
    printf("%d\\n", lca(s, t));
  }

  return 0;
}