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

#include <bits/stdc++.h>
using namespace std;
typedef vector<vector<int>> Graph;
typedef long long int ll;

Graph ginput(int n, int m) {
  Graph G(n);
  for (int i = 0; i < m; i++) {
    int s, t;
    cin >> s >> t;
    s--;
    t--;
    G[s].push_back(t);
    G[t].push_back(s);
  }
  return G;
}

vector<Graph> Forest2Trees(Graph &G) {
  int n = (int)G.size();
  vector<int> vtxid(n, -1);

  vector<Graph> ret;
  for (int i = 0; i < n; i++) {
    if (vtxid[i] >= 0)
      continue;
    Graph Tree(1);
    int cur = 0;
    vtxid[i] = cur++;

    queue<int> q;
    q.push(i);
    while (!q.empty()) {
      int k = q.front();
      q.pop();
      for (size_t x = 0; x < G[k].size(); x++) {
        int to = G[k][x];
        if (vtxid[to] >= 0)
          continue;
        vtxid[to] = cur++;
        Tree.push_back(vector<int>());
        Tree[vtxid[k]].push_back(vtxid[to]);
        Tree[vtxid[to]].push_back(vtxid[k]);
        q.push(to);
      }
    }
    ret.push_back(Tree);
  }
  return ret;
}

void dfs(int p, Graph &G, vector<int> &dist) {
  if (dist[p] == -1)
    dist[p] = 0;
  int cur = dist[p];
  for (size_t i = 0; i < G[p].size(); i++) {
    int to = G[p][i];
    if (dist[to] != -1)
      continue;
    dist[to] = cur + 1;
    dfs(to, G, dist);
  }
}

vector<int> getCenters(Graph &G) {
  int n = (int)G.size();
  vector<int> d0(n, -1), d1(n, -1), d2(n, -1);
  dfs(0, G, d0);
  int p1 = max_element(d0.begin(), d0.end()) - d0.begin();
  dfs(p1, G, d1);
  int p2 = max_element(d1.begin(), d1.end()) - d1.begin();
  dfs(p2, G, d2);

  vector<int> ret;
  int diameter = d2[p1];
  for (int i = 0; i < n; i++) {
    bool b1 = (d1[i] + d2[i] == diameter);
    bool b2 = (d1[i] == diameter / 2 || d2[i] == diameter / 2);
    if (b1 && b2)
      ret.push_back(i);
  }
  return ret;
}

map<string, ll> HASHMAP;
ll cntPattern, TreeHash;

ll getHash(Graph &G, int point, int parent = -1) {
  // leaf
  if (G[point].size() == 1 && parent != -1)
    return HASHMAP["0"] = 1;

  vector<string> rec;
  for (size_t i = 0; i < G[point].size(); i++) {
    int to = G[point][i];
    if (to == parent)
      continue;
    ll temp = getHash(G, to, point);
    rec.push_back(to_string(temp));
  }
  sort(rec.begin(), rec.end());
  string pat = "";
  for (size_t i = 0; i < rec.size(); i++)
    pat += rec[i];
  if (!HASHMAP.count(pat))
    HASHMAP[pat] = ++cntPattern;
  return HASHMAP[pat];
}

int main() {
  cntPattern = 1;
  int s1, s2;
  int n1, m1;
  cin >> n1 >> m1;
  Graph Forest = ginput(n1, m1);
  vector<Graph> Trees = Forest2Trees(Forest);

  int n2;
  cin >> n2;
  Graph Pattern = ginput(n2, n2 - 1);
  vector<int> patCenters = getCenters(Pattern);
  s1 = (int)patCenters.size();
  vector<ll> patHashes;
  for (int i = 0; i < s1; i++)
    patHashes.push_back(getHash(Pattern, patCenters[i]));

  int ans = 0;
  for (size_t i = 0; i < Trees.size(); i++) {
    if (Trees[i].size() != Pattern.size())
      continue;
    vector<int> treeCenters = getCenters(Trees[i]);
    s2 = (int)treeCenters.size();
    if (s1 != s2)
      continue;
    for (int j = 0; j < s2; j++) {
      ll treeHash = getHash(Trees[i], treeCenters[j]);
      if (treeHash == patHashes[0]) {
        ans++;
        break;
      }
    }
  }
  cout << ans << endl;
  return 0;
}

Error: TLE

Fixed submission:

#include <algorithm>
#include <cstdio>
#include <cstring>
#include <functional>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <sstream>
#include <string>
#include <vector>
#define MOD 1000000007LL
using namespace std;
typedef long long ll;
typedef pair<int, int> P;

int n[2], m[2];
vector<int> G[2][400001];
int dist[400001];
int dist2[400001];
bool used[400001];
vector<int> root[2];
vector<int> vs;
map<string, int> mp;
vector<int> vp;
int cnt = 0;

char buf[3145140];
char *end;

int calc(int t, int v, int parent) {
  vector<int> s;
  for (int i = 0; i < (int)G[t][v].size(); i++) {
    int nv = G[t][v][i];
    if (parent != nv) {
      int val = calc(t, nv, v);
      if (val == -1)
        return -1;
      s.push_back(val);
    }
  }
  if (s.size() > 0)
    sort(s.begin(), s.end());
  string str = "";
  for (int i = 0; i < s.size(); i++) {
    str += to_string(s[i]);
  }
  if (str.size() == 0) {
    str += '0';
  }
  if ((int)mp.count(str) == 1) {
    return mp[str];
  } else {
    if (t == 0)
      return -1;
    int siz = cnt++;
    mp.insert(map<string, int>::value_type(str, siz + 1));
    return siz + 1;
  }
  return -1;
}

void bfs(int t, int s) {
  queue<int> que;
  memset(dist, -1, sizeof(dist));
  vs.clear();
  que.push(s);
  dist[s] = 0;
  while (que.size()) {
    int v = que.front();
    que.pop();
    vs.push_back(v);
    for (int i = 0; i < G[t][v].size(); i++) {
      if (dist[G[t][v][i]] == -1) {
        dist[G[t][v][i]] = dist[v] + 1;
        que.push(G[t][v][i]);
      }
    }
  }
}

void solve() {
  bfs(1, 0);
  int maxi = -1;
  int tgt = 0;
  for (int i = 0; i < n[1]; i++) {
    if (dist[i] > maxi) {
      maxi = dist[i];
      tgt = i;
    }
  }
  bfs(1, tgt);
  maxi = -1;
  for (int i = 0; i < n[1]; i++) {
    if (dist[i] > maxi) {
      maxi = dist[i];
      tgt = i;
    }
  }
  int maxi2 = maxi;
  for (int i = 0; i < n[1]; i++) {
    dist2[i] = dist[i];
  }
  bfs(1, tgt);
  for (int i = 0; i < n[1]; i++) {
    if (maxi % 2 == 0) {
      if (dist[i] == maxi / 2 && dist2[i] == maxi / 2)
        root[1].push_back(i);
    } else {
      if (dist[i] == (maxi + 1) / 2 && dist2[i] == maxi / 2)
        root[1].push_back(i);
      if (dist[i] == maxi / 2 && dist2[i] == (maxi + 1) / 2)
        root[1].push_back(i);
    }
  }
  for (int i = 0; i < root[1].size(); i++) {
    vp.push_back(calc(1, root[1][i], -1));
  }
  int res = 0;
  for (int i = 0; i < n[0]; i++) {
    if (!used[i]) {
      root[0].clear();
      bfs(0, i);
      maxi = -1;
      tgt = 0;
      for (int j = 0; j < vs.size(); j++) {
        int v = vs[j];
        if (dist[v] > maxi) {
          maxi = dist[v];
          tgt = v;
        }
        used[v] = true;
      }
      if (vs.size() != n[1])
        continue;
      bfs(0, tgt);
      maxi = -1;
      for (int j = 0; j < vs.size(); j++) {
        int v = vs[j];
        if (dist[v] > maxi) {
          maxi = dist[v];
          tgt = v;
        }
        dist2[v] = dist[v];
      }
      if (maxi != maxi2)
        continue;
      bfs(0, tgt);
      for (int j = 0; j < vs.size(); j++) {
        int v = vs[j];
        if (maxi % 2 == 0) {
          if (dist[v] == maxi / 2 && dist2[v] == maxi / 2)
            root[0].push_back(v);
        } else {
          if (dist[v] == (maxi + 1) / 2 && dist2[v] == maxi / 2)
            root[0].push_back(v);
          if (dist[v] == maxi / 2 && dist2[v] == (maxi + 1) / 2)
            root[0].push_back(v);
        }
      }
      bool flag = false;
      for (int j = 0; j < root[0].size(); j++) {
        int s1 = calc(0, root[0][j], -1);
        for (int k = 0; k < vp.size(); k++) {
          if (s1 == vp[k])
            flag = true;
        }
      }
      if (flag)
        res++;
    }
  }
  printf("%d\\n", res);
}

int main(void) {
  scanf("%d%d", &n[0], &m[0]);
  for (int i = 0; i < m[0]; i++) {
    int f, t;
    scanf("%d%d", &f, &t);
    f--;
    t--;
    G[0][f].push_back(t);
    G[0][t].push_back(f);
  }

  scanf("%d", &n[1]);
  m[1] = n[1] - 1;
  for (int i = 0; i < m[1]; i++) {
    int f, t;
    scanf("%d%d", &f, &t);
    f--;
    t--;
    G[1][f].push_back(t);
    G[1][t].push_back(f);
  }
  solve();
  return 0;
}