Problem p01090 (C++) — buggy submission, verdict: Runtime Error

#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>

#include <algorithm>
#include <complex>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <stack>
#include <string>
#include <unordered_map>
#include <unordered_set>
#include <vector>

#include <cassert>
#include <functional>

typedef long long ll;
using namespace std;

#define debug(x) cerr << __LINE__ << " : " << #x << " = " << (x) << endl;

#define mod 1000000007              // 1e9+7(prime number)
#define INF 1000000000              // 1e9
#define LLINF 2000000000000000000LL // 2e18
#define SIZE 100010

/* UnionFind */

struct UnionFind {
  vector<int> data, tree_size;
  UnionFind(int s) : data(s, -1), tree_size(s, 1) {}

  int root(int x) {
    // debug(x);
    if (data[x] == -1)
      return x;
    return data[x] = root(data[x]);
  }

  bool set(int x, int y) {
    x = root(x);
    y = root(y);
    if (x == y)
      return false;
    data[y] = x;
    tree_size[x] += tree_size[y];
    tree_size[y] = 0;
    return true;
  }

  bool check(int x, int y) {
    x = root(x);
    y = root(y);
    return x == y;
  }

  int size(int x) { return tree_size[root(x)]; }
};

int n, m, k;
int u[SIZE], v[SIZE], w[SIZE], l[SIZE];

int check(int x) {
  vector<pair<int, int>> vec;
  int sum = 0;

  for (int i = 0; i < m; i++) {
    vec.push_back({(w[i] + x * !l[i]) * 2 + l[i], i});
  }

  sort(vec.begin(), vec.end());

  int counter = 0, Acounter = 0;
  UnionFind uf(n);

  for (int i = 0; i < m; i++) {
    if (uf.set(u[vec[i].second], v[vec[i].second])) {
      counter++;
      Acounter += !l[vec[i].second];
    }
  }

  if (counter == n - 1)
    return Acounter;
  else
    return -1;
}

int make(int x) {
  vector<pair<int, int>> vec;
  int sum = 0;

  for (int i = 0; i < m; i++) {
    vec.push_back({(w[i] + x * !l[i]) * 2 + l[i], i});
  }

  sort(vec.begin(), vec.end());

  int counter = 0, Acounter = 0;
  int limit = k;
  UnionFind uf(n);

  for (int i = 0; i < m; i++) {
    if (limit <= 0 && !l[vec[i].second])
      continue;
    if (uf.set(u[vec[i].second], v[vec[i].second])) {
      counter++;
      Acounter += !l[vec[i].second];
      sum += w[vec[i].second] + x * !l[vec[i].second];
      // limit -= !l[vec[i].second];
    }
  }

  assert(counter == n - 1);

  return sum;
}

bool solve() {

  scanf("%d%d%d", &n, &m, &k);
  if (n == 0)
    return false;

  for (int i = 0; i < m; i++) {
    char c;
    scanf("%d%d%d %c", u + i, v + i, w + i, &c);
    u[i]--;
    v[i]--;
    l[i] = c - 'A';
    // debug(u[i]); debug(v[i]);
    assert(u[i] < n && v[i] < n);
  }

  int L = -200, R = 200;

  // cerr << check(L,0) << "-" <<  check(R+1,0) << endl;
  // cerr << check(L,1) << "-" <<  check(R+1,1) << endl;

  if (check(L) == -1 || (k < check(R) || check(L) < k)) {
    puts("-1");
    return true;
  }

  while (L < R) {
    int mid = (L + R + 1) / 2;

    if (check(mid) < k) {
      R = mid - 1;
    } else {
      L = mid;
    }
  }

  // debug(L * k);

  int res = make(L);

  // debug(res);

  cout << res - L * k << endl;

  return true;
}

int main() {
  while (solve())
    ;

  return 0;
}


Error: -11

Fixed submission:

#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>

#include <algorithm>
#include <complex>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <stack>
#include <string>
#include <unordered_map>
#include <unordered_set>
#include <vector>

#include <cassert>
#include <functional>

typedef long long ll;
using namespace std;

#define debug(x) cerr << __LINE__ << " : " << #x << " = " << (x) << endl;

#define mod 1000000007              // 1e9+7(prime number)
#define INF 1000000000              // 1e9
#define LLINF 2000000000000000000LL // 2e18
#define SIZE 1010

/* Aho Corasick */

struct ACNode;

ACNode *pos[SIZE];
int pos_size = 0;

struct ACNode {
  int val, id;
  ACNode *next[26], *failure;

  ACNode() : val(0) { memset(next, 0, sizeof(next)); }

  void insert(char *s) {
    if (!*s) {
      val++;
      return;
    }
    int al = *s - 'a';
    if (next[al] == NULL) {
      next[al] = new ACNode;
      next[al]->id = pos_size;
      pos[pos_size++] = next[al];
    }
    next[al]->insert(s + 1);
  }

  ACNode *nextNode(char c) {
    int al = c - 'a';
    if (next[al])
      return next[al];
    return failure == this ? this : failure->nextNode(c);
  }
};

struct AhoCorasick {
  ACNode *node;

  AhoCorasick() { node = new ACNode; }

  void insert(char *s) { node->insert(s); }

  void build() {
    queue<ACNode *> que;
    que.push(node);
    node->failure = node;

    while (que.size()) {
      ACNode *p = que.front();
      que.pop();

      for (int i = 0; i < 26; i++) {
        if (p->next[i]) {
          ACNode *failure = p->failure;
          while (!failure->next[i] && failure != node) {
            failure = failure->failure;
          }
          if (failure->next[i] && failure != p) {
            p->next[i]->failure = failure->next[i];
            p->next[i]->val += failure->next[i]->val;
          } else {
            p->next[i]->failure = node;
          }
          que.push(p->next[i]);
        }
      }
    }
  }
};

struct DATA {
  int now;
  int acpos;
  bool usessword;

  const bool operator<(const DATA b) const {
    if (now != b.now)
      return now < b.now;
    if (acpos != b.acpos)
      return acpos < b.acpos;
    return usessword < b.usessword;
  }
};

int n, m, q;
string from[SIZE], to[SIZE], ssword[SIZE];
int fromid[SIZE], toid[SIZE];
string word[SIZE];

bool solve() {
  map<string, int> dict;
  vector<int> way[SIZE];

  scanf("%d%d%d", &n, &m, &q);

  if (n == 0)
    return false;

  for (int i = 0; i < n; i++) {
    cin >> from[i] >> to[i];

    if (dict.find(from[i]) == dict.end()) {
      word[dict.size()] = from[i];
      dict[from[i]] = dict.size();
    }
    if (dict.find(to[i]) == dict.end()) {
      word[dict.size()] = to[i];
      dict[to[i]] = dict.size();
    }

    fromid[i] = dict[from[i]];
    toid[i] = dict[to[i]];

    way[fromid[i]].push_back(toid[i]);
  }

  AhoCorasick ac;
  pos[pos_size++] = ac.node;
  ac.node->id = 0;

  for (int i = 0; i < q; i++) {
    char ssword[50];
    scanf("%s", ssword);
    ac.insert(ssword);
  }

  ac.build();

  for (int i = 0; i < dict.size(); i++) {
    way[dict.size()].push_back(i);
  }

  map<DATA, ll> data[500];
  DATA initData = {(int)dict.size(), 0, false};
  data[0][initData] = 1;

  for (int i = 0; i < m; i++) {
    for (auto it : data[i]) {
      auto p = it.first;
      ll val = it.second;

      for (int j = 0; j < way[p.now].size(); j++) {
        int l = word[way[p.now][j]].size();
        if (i + l <= m) {
          auto acpos = pos[p.acpos];
          int v = 0;
          for (int k = 0; k < l; k++) {
            acpos = acpos->nextNode(word[way[p.now][j]][k]);
            v += acpos->val;
          }

          if (v + p.usessword <= 1) {
            DATA newdata = {way[p.now][j], acpos->id, v + p.usessword > 0};
            data[i + l][newdata] = (data[i + l][newdata] + val) % mod;
          }
        }
      }
    }
  }

  ll ans = 0;

  for (auto it : data[m]) {
    if (it.first.usessword)
      ans = (it.second + ans) % mod;
  }

  printf("%lld\\n", ans);

  for (int i = 0; i < pos_size; i++) {
    free(pos[i]);
  }
  pos_size = 0;

  return true;
}

int main() {
  while (solve())
    ;

  return 0;
}