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

#include <algorithm>
#include <iostream>
#include <list>
#include <set>
#include <string>
#include <vector>

typedef int node_t;

struct arrow_t {
  node_t source;
  node_t sink;
  std::string label;
};

struct entry_t {
  std::string label;
  std::set<node_t> nodes;

  entry_t() {}
  entry_t(const std::string &label) : label(label) {}
};

typedef std::list<entry_t> queue_t;

int compare(const std::string &s1, const std::string &s2) {
  for (std::string::const_iterator i1 = s1.begin(), i2 = s2.begin();;
       ++i1, ++i2) {
    if (i1 == s1.end()) {
      return i2 == s2.end() ? 0 : -1;
    } else if (i2 == s2.end()) {
      return 1;
    }
    int c = ((int)*i1) - ((int)*i2);
    if (c != 0) {
      return c < 0 ? -2 : 2;
    }
  }
  return 0;
}

queue_t::iterator insert(queue_t &queue, const std::string &label) {
  for (queue_t::iterator it = queue.begin(); it != queue.end(); it++) {
    switch (compare(it->label, label)) {
    case -2:
      return queue.end();
    case -1:
      continue;
    case 0:
      return it;
    case 1:
      return queue.insert(it, entry_t(label));
    case 2:
      return queue.insert(queue.erase(it, queue.end()), entry_t(label));
    }
  }
  return queue.insert(queue.end(), entry_t(label));
}

std::set<node_t> collect(int n, const std::vector<arrow_t> &arrows,
                         node_t goal) {
  std::vector<std::vector<node_t>> ins(n);
  for (const arrow_t &arrow : arrows) {
    ins[arrow.sink].push_back(arrow.source);
  }

  std::set<node_t> result;
  std::vector<node_t> stack;
  stack.push_back(goal);
  while (!stack.empty()) {
    node_t node = stack.back();
    stack.pop_back();

    result.insert(node);

    for (int source : ins[node]) {
      if (result.find(source) == result.end()) {
        stack.push_back(source);
      }
    }
  }
  return result;
}

std::string calc(int n, const std::vector<arrow_t> &arrows, node_t start,
                 node_t goal) {
  const std::set<node_t> &reachable_set = collect(n, arrows, goal);
  if (reachable_set.find(start) == reachable_set.end()) {
    return "NO";
  }

  size_t max = 0;
  std::vector<std::vector<const arrow_t *>> outs(n);
  for (const arrow_t &arrow : arrows) {
    if (reachable_set.find(arrow.sink) != reachable_set.end()) {
      max = std::max(max, arrow.label.size());
      outs[arrow.source].push_back(&arrow);
    }
  }

  size_t limit = n * max;

  std::string result;
  queue_t queue;
  queue.push_back(entry_t());
  queue.front().nodes.insert(start);
  while (!queue.empty()) {
    std::string label = queue.front().label;
    std::set<node_t> nodes = queue.front().nodes;
    queue.pop_front();

    result.append(label.begin(), label.end());
    if (nodes.find(goal) != nodes.end()) {
      return result;
    }
    if (result.size() > limit) {
      return "NO";
    }

    int size = label.size();
    for (entry_t &entry : queue) {
      entry.label.erase(0, size);
    }

    for (node_t node : nodes) {
      for (const arrow_t *arrow : outs[node]) {
        queue_t::iterator it = insert(queue, arrow->label);
        if (it != queue.end()) {
          it->nodes.insert(arrow->sink);
        }
      }
    }
  }
  return "?";
}

int main() {
  while (true) {
    int n, a, s, g;
    std::cin >> n >> a >> s >> g;
    if (n == 0) {
      break;
    }
    std::vector<arrow_t> arrows(a);
    for (arrow_t &arrow : arrows) {
      std::cin >> arrow.source >> arrow.sink >> arrow.label;
    }
    std::cout << calc(n, arrows, s, g) << std::endl;
  }
  return 0;
}

Error: 0

Fixed submission:

#include <algorithm>
#include <iostream>
#include <list>
#include <set>
#include <string>
#include <vector>

typedef int node_t;

struct arrow_t {
  node_t source;
  node_t sink;
  std::string label;
};

struct entry_t {
  std::string label;
  std::set<node_t> nodes;

  entry_t() {}
  entry_t(const std::string &label) : label(label) {}
};

typedef std::list<entry_t> queue_t;

int compare(const std::string &s1, const std::string &s2) {
  size_t size1 = s1.size();
  size_t size2 = s2.size();
  for (size_t i = 0;; i++) {
    if (i == size1) {
      return i == size2 ? 0 : -1;
    } else if (i == size2) {
      return 1;
    }
    int c = ((int)s1[i]) - ((int)s2[i]);
    if (c != 0) {
      return c < 0 ? -2 : 2;
    }
  }
  return 0;
}

queue_t::iterator insert(queue_t &queue, const std::string &label) {
  for (queue_t::iterator it = queue.begin(); it != queue.end(); it++) {
    switch (compare(it->label, label)) {
    case -2:
      return queue.end();
    case -1:
      continue;
    case 0:
      return it;
    case 1:
      return queue.insert(it, entry_t(label));
    case 2:
      return queue.insert(queue.erase(it, queue.end()), entry_t(label));
    }
  }
  return queue.insert(queue.end(), entry_t(label));
}

std::set<node_t> collect(int n, const std::vector<arrow_t> &arrows,
                         node_t goal) {
  std::vector<std::vector<node_t>> ins(n);
  for (int i = 0; i < arrows.size(); i++) {
    const arrow_t &arrow = arrows[i];
    ins[arrow.sink].push_back(arrow.source);
  }

  std::set<node_t> result;
  std::vector<node_t> stack;
  stack.push_back(goal);
  while (!stack.empty()) {
    node_t node = stack.back();
    stack.pop_back();

    result.insert(node);

    for (int source : ins[node]) {
      if (result.find(source) == result.end()) {
        stack.push_back(source);
      }
    }
  }
  return result;
}

std::string calc(int n, const std::vector<arrow_t> &arrows, node_t start,
                 node_t goal) {
  const std::set<node_t> &reachable_set = collect(n, arrows, goal);
  if (reachable_set.find(start) == reachable_set.end()) {
    return "NO";
  }

  size_t max = 0;
  std::vector<std::vector<const arrow_t *>> outs(n);
  for (const arrow_t &arrow : arrows) {
    if (reachable_set.find(arrow.sink) != reachable_set.end()) {
      max = std::max(max, arrow.label.size());
      outs[arrow.source].push_back(&arrow);
    }
  }

  size_t limit = n * max;

  std::string result;
  queue_t queue;
  queue.push_back(entry_t());
  queue.front().nodes.insert(start);
  while (!queue.empty()) {
    std::string label = queue.front().label;
    std::set<node_t> nodes = queue.front().nodes;
    queue.pop_front();

    result += label;
    if (nodes.find(goal) != nodes.end()) {
      return result;
    }
    if (result.size() > limit) {
      return "NO";
    }

    int size = label.size();
    for (entry_t &entry : queue) {
      entry.label.erase(0, size);
    }

    for (node_t node : nodes) {
      for (const arrow_t *arrow : outs[node]) {
        queue_t::iterator it = insert(queue, arrow->label);
        if (it != queue.end()) {
          it->nodes.insert(arrow->sink);
        }
      }
    }
  }
  return "?";
}

int main() {
  while (true) {
    int n, a, s, g;
    std::cin >> n >> a >> s >> g;
    if (n == 0) {
      break;
    }
    std::vector<arrow_t> arrows(a);
    for (int i = 0; i < arrows.size(); i++) {
      arrow_t &arrow = arrows[i];
      std::cin >> arrow.source >> arrow.sink >> arrow.label;
    }
    std::cout << calc(n, arrows, s, g) << std::endl;
  }
  return 0;
}