Problem p01913 (C++)

Buggy submission (status: Memory Limit Exceeded):
#include <algorithm>
#include <array>
#include <bitset>
#include <cassert>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iomanip>
#include <iostream>
#include <map>
#include <numeric>
#include <queue>
#include <random>
#include <set>
#include <unordered_map>
#include <unordered_set>
#include <vector>

using namespace std;
using uint = unsigned int;
using ll = long long;
using ull = unsigned long long;
template <class T> using V = vector<T>;
template <class T> using VV = V<V<T>>;
constexpr ll TEN(int n) { return (n == 0) ? 1 : 10 * TEN(n - 1); }

int rand_int(int a, int b) {
  static random_device rd;
  static mt19937 gen(rd());
  return uniform_int_distribution<int>(a, b)(gen);
}

struct UnionFind {
  V<int> id;
  V<int> data;
  VV<int> groups;
  UnionFind(int n) {
    id = V<int>(n);
    data = V<int>(n);
    groups = VV<int>(n);
    for (int i = 0; i < n; i++) {
      id[i] = i;
      groups[i].push_back(i);
    }
  }
  void setd(int a, int x) {
    data[id[a]] = x;
    return;
  }
  int getd(int a) { return data[id[a]]; }

  bool same(int a, int b) { return id[a] == id[b]; }
  void merge(int a, int b) {
    if (same(a, b))
      return;
    int x = id[a], y = id[b];
    if (groups[x].size() > groups[y].size())
      swap(x, y);
    for (int d : groups[y]) {
      id[d] = x;
      groups[x].push_back(d);
    }
    groups[y].clear();
  }
};
using P = pair<int, int>;
const int MN = 300300;
V<P> ed[MN];

int n;
P vs[MN]; // start, size
V<int> g[MN];
ll pnt[MN];

void dfs(int p, int nw, ll sm) {
  //    cout << p << endl;
  sm += ll(vs[p].first - nw) * vs[p].second;
  if (p < n) {
    //        cout << "last " << p << " " << sm << endl;
    pnt[p] = sm;
    return;
  }
  for (int d : g[p]) {
    dfs(d, vs[p].first, sm);
  }
}

V<P> gg[MN]; // to, time

int main() {
  cin.tie(0);
  ios::sync_with_stdio(false);
  cout << setprecision(20);
  int m, t;
  cin >> n >> m >> t;
  for (int i = 0; i < m; i++) {
    int a, b, t;
    cin >> a >> b >> t;
    a--;
    b--;
    t--;
    ed[t].push_back(P(a, b));
    gg[a].push_back(P(b, t));
    gg[b].push_back(P(a, t));
  }
  UnionFind uf(n);
  for (int i = 0; i < n; i++) {
    vs[i] = P(t, 1);
    uf.setd(i, i);
  }
  int vc = n;
  for (int i = t - 1; i >= 0; i--) {
    for (auto p : ed[i]) {
      int a, b;
      tie(a, b) = p;
      if (uf.same(a, b))
        continue;
      int ad = uf.getd(a);
      int bd = uf.getd(b);
      uf.merge(a, b);
      int vid = vc;
      vc++;
      vs[vid] = P(i + 1, vs[ad].second + vs[bd].second);
      g[vid].push_back(ad);
      g[vid].push_back(bd);
      uf.setd(a, vid);
    }
  }
  dfs(vc - 1, 0, 0);

  ll ans = 0;
  queue<P> que;
  V<bool> used(n);
  que.push(P(0, 0));
  while (!que.empty()) {
    P p = que.front();
    que.pop();
    int a, tm;
    tie(a, tm) = p;
    if (used[a])
      continue;
    used[a] = true;
    ans = max(ans, pnt[a]);
    for (auto ed : gg[a]) {
      if (ed.second < tm)
        continue;
      que.push(P(ed.first, tm + 1));
    }
  }

  cout << ans << endl;
  return 0;
}

Fixed submission:
#include <algorithm>
#include <array>
#include <bitset>
#include <cassert>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iomanip>
#include <iostream>
#include <map>
#include <numeric>
#include <queue>
#include <random>
#include <set>
#include <unordered_map>
#include <unordered_set>
#include <vector>

using namespace std;
using uint = unsigned int;
using ll = long long;
using ull = unsigned long long;
template <class T> using V = vector<T>;
template <class T> using VV = V<V<T>>;
constexpr ll TEN(int n) { return (n == 0) ? 1 : 10 * TEN(n - 1); }

int rand_int(int a, int b) {
  static random_device rd;
  static mt19937 gen(rd());
  return uniform_int_distribution<int>(a, b)(gen);
}

struct UnionFind {
  V<int> id;
  V<int> data;
  VV<int> groups;
  UnionFind(int n) {
    id = V<int>(n);
    data = V<int>(n);
    groups = VV<int>(n);
    for (int i = 0; i < n; i++) {
      id[i] = i;
      groups[i].push_back(i);
    }
  }
  void setd(int a, int x) {
    data[id[a]] = x;
    return;
  }
  int getd(int a) { return data[id[a]]; }

  bool same(int a, int b) { return id[a] == id[b]; }
  void merge(int a, int b) {
    if (same(a, b))
      return;
    int x = id[a], y = id[b];
    if (groups[x].size() < groups[y].size())
      swap(x, y);
    for (int d : groups[y]) {
      id[d] = x;
      groups[x].push_back(d);
    }
    groups[y].clear();
  }
};
using P = pair<int, int>;
const int MN = 300300;
V<P> ed[MN];

int n;
P vs[MN]; // start, size
V<int> g[MN];
ll pnt[MN];

void dfs(int p, int nw, ll sm) {
  //    cout << p << endl;
  sm += ll(vs[p].first - nw) * vs[p].second;
  if (p < n) {
    //        cout << "last " << p << " " << sm << endl;
    pnt[p] = sm;
    return;
  }
  for (int d : g[p]) {
    dfs(d, vs[p].first, sm);
  }
}

V<P> gg[MN]; // to, time

int main() {
  cin.tie(0);
  ios::sync_with_stdio(false);
  cout << setprecision(20);
  int m, t;
  cin >> n >> m >> t;
  for (int i = 0; i < m; i++) {
    int a, b, t;
    cin >> a >> b >> t;
    a--;
    b--;
    t--;
    ed[t].push_back(P(a, b));
    gg[a].push_back(P(b, t));
    gg[b].push_back(P(a, t));
  }
  UnionFind uf(n);
  for (int i = 0; i < n; i++) {
    vs[i] = P(t, 1);
    uf.setd(i, i);
  }
  int vc = n;
  for (int i = t - 1; i >= 0; i--) {
    for (auto p : ed[i]) {
      int a, b;
      tie(a, b) = p;
      if (uf.same(a, b))
        continue;
      int ad = uf.getd(a);
      int bd = uf.getd(b);
      uf.merge(a, b);
      int vid = vc;
      vc++;
      vs[vid] = P(i + 1, vs[ad].second + vs[bd].second);
      g[vid].push_back(ad);
      g[vid].push_back(bd);
      uf.setd(a, vid);
    }
  }
  dfs(vc - 1, 0, 0);

  ll ans = 0;
  queue<P> que;
  V<bool> used(n);
  que.push(P(0, 0));
  while (!que.empty()) {
    P p = que.front();
    que.pop();
    int a, tm;
    tie(a, tm) = p;
    if (used[a])
      continue;
    used[a] = true;
    ans = max(ans, pnt[a]);
    for (auto ed : gg[a]) {
      if (ed.second < tm)
        continue;
      que.push(P(ed.first, tm + 1));
    }
  }

  cout << ans << endl;
  return 0;
}