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

#include "bits/stdc++.h"
using namespace std;

using VS = vector<string>;
using LL = long long;
using VI = vector<int>;
using VVI = vector<VI>;
using PII = pair<int, int>;
using PLL = pair<LL, LL>;
using VL = vector<LL>;
using VVL = vector<VL>;

#define ALL(a) begin((a)), end((a))
#define RALL(a) (a).rbegin(), (a).rend()
#define SZ(a) int((a).size())
#define SORT(c) sort(ALL((c)))
#define RSORT(c) sort(RALL((c)))
#define UNIQ(c) (c).erase(unique(ALL((c))), end((c)))
#define FOR(i, s, e) for (int(i) = (s); (i) < (e); (i)++)
#define FORR(i, s, e) for (int(i) = (s); (i) > (e); (i)--)
#define debug(x) cerr << #x << ": " << x << endl
const int INF = 1e9;
const LL LINF = 1e16;
const LL MOD = 1000000007;
const double PI = acos(-1.0);
int DX[8] = {0, 0, 1, -1, 1, 1, -1, -1};
int DY[8] = {1, -1, 0, 0, 1, -1, 1, -1};

struct UnionFind {
  vector<int> data;
  UnionFind(int n) { data.assign(n, -1); }
  bool unionSet(int x, int y) {
    x = root(x);
    y = root(y);
    if (x != y) {
      if (data[y] < data[x])
        swap(x, y);
      data[x] += data[y];
      data[y] = x;
    }
    return x != y;
  }
  bool same(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)]; }
};

struct TwoEdgeConnectedComponent {
  UnionFind uf;
  vector<vector<int>> g;
  vector<pair<int, int>> edges;
  vector<int> used, ord, low, comp;

  TwoEdgeConnectedComponent(int v)
      : uf(v), g(v), used(v, 0), comp(v), ord(v), low(v) {}

  void add_edge(int x, int y) {
    g[x].push_back(y);
    g[y].push_back(x);
    edges.push_back(minmax(x, y));
  }

  void dfs(int idx, int &k, int par = -1) {
    used[idx] = true;
    ord[idx] = k++;
    low[idx] = ord[idx];

    for (auto &to : g[idx]) {
      if (!used[to]) {
        dfs(to, k, idx);
        low[idx] = min(low[idx], low[to]);
        if (ord[idx] >= low[to])
          uf.unionSet(idx, to);
      } else if (to != par) {
        low[idx] = min(low[idx], ord[to]);
      }
    }
  }

  // return origin color
  int operator[](int k) { return (comp[k]); }

  int size() { return (g.size()); }

  // build, renew resG(empty -> tree), return color
  vector<int> get_graph(vector<vector<int>> &resG, int root = 0) {
    int kk = 0;
    dfs(root, kk);

    int ptr = 0;
    vector<int> color(g.size());
    for (int i = 0; i < g.size(); i++) {
      if (i == uf.root(i))
        color[i] = ptr++;
    }

    resG.resize(ptr);
    for (int i = 0; i < g.size(); i++) {
      comp[i] = color[uf.root(i)];
    }
    for (auto &e : edges) {
      int x = comp[e.first], y = comp[e.second];
      if (x == y)
        continue;
      resG[x].push_back(y);
      resG[y].push_back(x);
    }
    // TLE
    //        for (int v = 0; v < (int)g.size(); v++) {
    //            for (int i = 0; i < (int)g[v].size(); i++) {
    //                int u = g[v][i];
    //                int c1 = comp[v], c2 = comp[u];
    //                if (c1 == c2)continue;
    //                resG[c1].push_back(c2);
    //                resG[c2].push_back(c1);
    //            }
    //        }
    return comp;
  }
};

int N, M, W[100000];
vector<vector<int>> resG;
vector<int> weightSum, sz;
int dp1[100000], dp3[100000];

int rec(int idx, int par = -1) {
  int ret = 0;
  for (auto &to : resG[idx]) {
    if (to == par)
      continue;
    ret = max(ret, rec(to, idx));
    dp1[idx] += dp1[to];
  }
  ret += weightSum[idx];
  if (sz[idx] >= 3 || dp1[idx] > 0)
    dp1[idx] += weightSum[idx];
  for (auto &to : resG[idx]) {
    if (to == par)
      continue;
    else
      ret = max(ret, dp1[idx] - dp1[to] + dp3[to]);
  }
  return (dp3[idx] = ret);
}

// 三点以上集まった頂点ならば、ここを起点にもどることができる。
// dp1[v]:vから葉まで進むときの最大値
// dp3[v]:vに戻ってくるときの最大値
void f(int v, int p = -1) {
  for (int nx : resG[v]) {
    if (nx == p)
      continue;
    f(nx, v);
    dp1[v] += dp1[nx];
  }
  int ret = dp1[v];
  if (dp1[v] || sz[v] > 1)
    dp1[v] += weightSum[v];
  for (int nx : resG[v]) {
    if (nx == p)
      continue;
    dp3[v] = max(dp3[v], ret - dp1[nx] + dp3[nx]);
  }
  dp3[v] += weightSum[v];
}

int main() {
  int N, M;
  cin >> N >> M;
  FOR(i, 0, N) { cin >> W[i]; }
  TwoEdgeConnectedComponent gx(N);

  FOR(i, 0, M) {
    int a, b;
    cin >> a >> b;
    a--, b--;
    gx.add_edge(a, b);
  }
  VI vc = gx.get_graph(resG);

  weightSum.assign(resG.size(), 0);
  sz.assign(resG.size(), 0);
  for (int i = 0; i < N; i++) {
    weightSum[vc[i]] += W[i];
    sz[vc[i]]++;
  }
  f(vc[0]);
  LL ans = dp3[vc[0]];
  cout << ans << endl;

  return 0;
}


Error: TLE

Fixed submission:

#include "bits/stdc++.h"
using namespace std;

using VS = vector<string>;
using LL = long long;
using VI = vector<int>;
using VVI = vector<VI>;
using PII = pair<int, int>;
using PLL = pair<LL, LL>;
using VL = vector<LL>;
using VVL = vector<VL>;

#define ALL(a) begin((a)), end((a))
#define RALL(a) (a).rbegin(), (a).rend()
#define SZ(a) int((a).size())
#define SORT(c) sort(ALL((c)))
#define RSORT(c) sort(RALL((c)))
#define UNIQ(c) (c).erase(unique(ALL((c))), end((c)))
#define FOR(i, s, e) for (int(i) = (s); (i) < (e); (i)++)
#define FORR(i, s, e) for (int(i) = (s); (i) > (e); (i)--)
#define debug(x) cerr << #x << ": " << x << endl
const int INF = 1e9;
const LL LINF = 1e16;
const LL MOD = 1000000007;
const double PI = acos(-1.0);
int DX[8] = {0, 0, 1, -1, 1, 1, -1, -1};
int DY[8] = {1, -1, 0, 0, 1, -1, 1, -1};

/*-----------------------------------------------
 二辺連結成分分解 成分だけ unverified
 -----------------------------------------------*/

struct UnionFind {
  vector<int> data;
  UnionFind(int n) { data.assign(n, -1); }
  bool unionSet(int x, int y) {
    x = root(x);
    y = root(y);
    if (x != y) {
      if (data[y] < data[x])
        swap(x, y);
      data[x] += data[y];
      data[y] = x;
    }
    return x != y;
  }
  bool same(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)]; }
};

struct Lowlink {
  UnionFind uf;
  vector<int> low, ord, used, parent;
  int root, k;
  Lowlink(int V, int Root)
      : uf(V), low(V), ord(V), used(V), parent(V), root(Root), k(0) {}

  void lowlink(int v, int p, int &k, vector<vector<int>> &G) {
    used[v] = true;
    low[v] = ord[v] = k;
    k++;
    for (int i = 0; i < (int)G[v].size(); i++) {
      int u = G[v][i];
      if (used[u] == 0) {
        parent[u] = v;
        lowlink(u, v, k, G);
        low[v] = min(low[v], low[u]);
        if (ord[v] >= low[u])
          uf.unionSet(v, u);
      } else if (u != p) {
        low[v] = min(low[v], ord[u]);
      }
    }
  }
};

struct TwoEdgeConnectedComponent : Lowlink {
  //   UnionFind uf;
  vector<vector<int>> g;
  vector<pair<int, int>> edges;
  vector<int> comp;
  TwoEdgeConnectedComponent(int v) : g(v), comp(v), Lowlink(v, 0) {}

  void add_edge(int x, int y) {
    g[x].push_back(y);
    g[y].push_back(x);
    edges.push_back(minmax(x, y));
  }
  // return origin color
  int operator[](int k) { return (comp[k]); }

  int size() { return (g.size()); }

  // build, renew resG(empty -> tree), return color
  vector<int> get_graph(vector<vector<int>> &resG, VI &W, VI &resW,
                        int root = 0) {
    int kk = 0;
    Lowlink::lowlink(root, -1, kk, g);
    int ptr = 0;
    vector<int> color(g.size());
    for (int i = 0; i < g.size(); i++) {
      if (i == uf.root(i))
        color[i] = ptr++;
    }

    resG.resize(ptr);
    for (int i = 0; i < g.size(); i++) {
      comp[i] = color[uf.root(i)];
    }

    resW.resize(ptr);
    for (int i = 0; i < (int)g.size(); i++) {
      comp[i] = color[uf.root(i)];
      // 頂点番号における写像を作る
      resW[comp[i]] += W[i]; // 重みをまとめる
    }
    //        for (auto &e : edges) {
    //            int x = comp[e.first], y = comp[e.second];
    //            if (x == y) continue;
    //            resG[x].push_back(y);
    //            resG[y].push_back(x);
    //        }

    for (int v = 0; v < (int)g.size(); v++) {
      for (int i = 0; i < (int)g[v].size(); i++) {
        int u = g[v][i];
        int c1 = comp[v], c2 = comp[u];
        if (c1 == c2)
          continue;
        resG[c1].push_back(c2);
        resG[c2].push_back(c1);
      }
    }
    return comp;
  }
};

LL dfs(int v, int p, VVI &G, VL &dp, VI &w) {
  LL res = 0;
  FOR(i, 0, SZ(G[v])) {
    int nx = G[v][i];
    if (nx == p)
      continue;
    res = max(res, dfs(nx, v, G, dp, w));
  }
  return dp[v] = res + w[v];
}

int main() {
  int N, M;
  vector<vector<int>> resG;

  cin >> N >> M;
  VI W(N);
  FOR(i, 0, N) { cin >> W[i]; }

  TwoEdgeConnectedComponent gx(N);
  FOR(i, 0, M) {
    int a, b;
    cin >> a >> b;
    a--, b--;
    gx.add_edge(a, b);
  }
  VI resW;
  VI vc = gx.get_graph(resG, W, resW);

  VL dp(N, 0);
  LL ans = dfs(0, -1, resG, dp, resW);
  cout << ans << endl;

  return 0;
}