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

#include <algorithm>
#include <cfloat>
#include <cmath>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <stack>
#include <stdio.h>
#include <string>
#include <time.h>
#include <vector>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define MOD 1000000007
#define EPS 0.000000001
using namespace std;

#define NUM 40
#define MAX_LEN 250

void strcpy(char *to, char *str) {
  to[0] = '\\0';
  for (int i = 0; str[i] != '\\0'; i++) {
    to[i] = str[i];
    to[i + 1] = '\\0';
  }
}

void strcpy2(char to[300], const char str[300]) {
  to[0] = '\\0';
  for (int i = 0; str[i] != '\\0'; i++) {
    to[i] = str[i];
    to[i + 1] = '\\0';
  }
}

void addcpy(char to[300], const char str[300]) {
  int index, second_index;
  for (index = 0; to[index] != '\\0'; index++)
    ;
  // printf("index:%d\\n",index);
  for (second_index = 0; str[second_index] != '\\0'; second_index++) {
    to[index + second_index] = str[second_index];
  }
  to[index + second_index] = '\\0';
}

bool strCmp(const char base[300], const char comp[300]) {
  int length1, length2;
  for (length1 = 0; base[length1] != '\\0'; length1++)
    ;
  for (length2 = 0; comp[length2] != '\\0'; length2++)
    ;
  if (length1 != length2)
    return false;

  for (int i = 0; base[i] != '\\0'; i++) {
    if (base[i] != comp[i])
      return false;
  }
  return true;
}

// 辞書順が等しい時は3,leftの方が早い場合は1,rightの方が早いときは2
int strCmp2(const char left[300], const char right[300]) {
  int i;

  if (strCmp(left, right))
    return 3;

  for (i = 0; left[i] != '\\0' && right[i] != '\\0'; i++) {
    if (left[i] != right[i]) {
      if (left[i] < right[i])
        return 1;
      else {
        return 2;
      }
    }
  }
  if (left[i] == '\\0')
    return 1;
  else {
    return 2;
  }
}

struct Edge {
  Edge(int arg_to, char arg_buf[7]) {
    to = arg_to;
    strcpy(buf, arg_buf);
    deleted = false;
  }
  int to;
  char buf[7];
  bool deleted;
};

struct Data {
  Data(int arg_node_id, int arg_edge_id) {
    node_id = arg_node_id;
    edge_id = arg_edge_id;
  }
  int node_id;
  int edge_id;
};

struct Info {
  Info(int arg_node_id, char arg_tmp_string[300]) {
    node_id = arg_node_id;
    strcpy(tmp_string, arg_tmp_string);
  }

  Info() { node_id = 0; }

  bool operator<(const struct Info &arg) const {
    int compare = strCmp2(tmp_string, arg.tmp_string);

    if (compare == 2 || compare == 3) { // argの方が早い
      return true;                      // PQなので逆
    } else {
      return false;
    }
  }
  int node_id;
  char tmp_string[300];
};

int N, E, start, goal;
char min_string[40][251][300]; // min_string[node_id][length][string]
bool reachable[NUM][NUM];
vector<Edge> G[NUM];

void func() {

  for (int i = 0; i < N; i++)
    G[i].clear();

  int from, to;
  char buf[7];

  for (int i = 0; i < N; i++) {
    for (int k = 0; k < N; k++) {
      if (i != k) {
        reachable[i][k] = false;
      } else {
        reachable[i][k] = true;
      }
    }
  }

  for (int i = 0; i < E; i++) {
    scanf("%d %d %s", &from, &to, buf);
    reachable[from][to] = true;
    G[from].push_back(Edge(to, buf));
  }

  for (int mid = 0; mid < N; mid++) {
    for (int st = 0; st < N; st++) {
      if (!reachable[st][mid])
        continue;
      for (int gl = 0; gl < N; gl++) {
        if (!reachable[mid][gl])
          continue;
        reachable[st][gl] = true;
      }
    }
  }

  if (!reachable[start][goal]) {
    printf("NO\\n");
    return;
  }

  int compare;

  // エッジを削る(同じノードかつ同じ行先)
  /*for(int i = 0; i < N; i++){
          for(int k = 0; k+1 < G[i].size(); k++){
                  if(G[i][k].deleted)continue;
                  for(int p = k+1; p < G[i].size(); p++){
                          if(G[i][k].to != G[i][p].to)continue;
                          if(G[i][k].buf[0] == G[i][p].buf[0])continue;
  //片方がもう片方に含まれる場合はSKIP

                          compare = strCmp2(G[i][k].buf,G[i][p].buf);

                          if(compare == 1){
                                  G[i][p].deleted = true;
                          }else{
                                  G[i][k].deleted = true;
                          }
                  }
          }
  }*/

  // bool check[N];

  // 長い文字列を記録
  for (int i = 0; i < N; i++) {
    // check[i] = false; //閉路に属しているか
    for (int length = 0; length < MAX_LEN; length++) {
      for (int k = 0; k <= length; k++) {
        min_string[i][length][k] = 'z';
      }
      min_string[i][length][length + 1] = '\\0';
    }
  }

  min_string[start][0][0] = '\\0';

  priority_queue<Info> Q;
  char first_string[300];
  first_string[0] = '\\0';

  Q.push(Info(start, first_string));
  int next_node, next_length;
  char ans[300], work[300];

  // int debug = 0;

  int length;

  while (!Q.empty()) {

    for (length = 0; Q.top().tmp_string[length] != '\\0'; length++)
      ;

    if (length >= 6 * N) {
      printf("NO\\n");
      return;
    }

    if (Q.top().node_id == goal) {

      printf("%s\\n", Q.top().tmp_string);
      return;
    } else if (strCmp2(Q.top().tmp_string,
                       min_string[Q.top().node_id][length]) == 2) {
      Q.pop();
    } else {

      for (int i = 0; i < G[Q.top().node_id].size(); i++) {
        // if(G[Q.top().node_id][i].deleted)continue;
        next_node = G[Q.top().node_id][i].to;
        // if(next_node == Q.top().node_id || reachable[next_node][goal] ==
        // false)continue; //自己ループ&ゴールに着けないノードは無視
        if (reachable[next_node][goal] == false)
          continue;

        // 新しい文字列を作る
        work[0] = '\\0';
        strcpy2(work, Q.top().tmp_string);
        // printf("work:%s tmp_str:%s\\n",work,Q.top().tmp_string);
        addcpy(work, G[Q.top().node_id][i].buf);
        // printf("work:%s buf:%s\\n",work,G[Q.top().node_id][i].buf);

        for (next_length = 0; work[next_length] != '\\0'; next_length++)
          ;

        if (strCmp2(work, min_string[next_node][next_length]) != 1)
          continue;
        strcpy2(min_string[next_node][next_length], work);

        Info next_info;
        next_info.node_id = next_node;
        strcpy(next_info.tmp_string, work);

        Q.push(next_info);
      }
      Q.pop();
    }
  }

  printf("NO\\n");
  return;
}

int main() {

  while (true) {
    scanf("%d %d %d %d", &N, &E, &start, &goal);
    if (N == 0 && E == 0 && start == 0 && goal == 0)
      break;

    func();
  }

  return 0;
}


Error: 0

Fixed submission:

#include <algorithm>
#include <cfloat>
#include <cmath>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <stack>
#include <stdio.h>
#include <string>
#include <time.h>
#include <vector>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define MOD 1000000007
#define EPS 0.000000001
using namespace std;

#define NUM 40

void strcpy(char *to, char *str) {
  to[0] = '\\0';
  for (int i = 0; str[i] != '\\0'; i++) {
    to[i] = str[i];
    to[i + 1] = '\\0';
  }
}

void strcpy2(char to[300], const char str[300]) {
  to[0] = '\\0';
  for (int i = 0; str[i] != '\\0'; i++) {
    to[i] = str[i];
    to[i + 1] = '\\0';
  }
}

void addcpy(char to[300], const char str[300]) {
  int index, second_index;
  for (index = 0; to[index] != '\\0'; index++)
    ;
  // printf("index:%d\\n",index);
  for (second_index = 0; str[second_index] != '\\0'; second_index++) {
    to[index + second_index] = str[second_index];
  }
  to[index + second_index] = '\\0';
}

bool strCmp(const char base[300], const char comp[300]) {
  int length1, length2;
  for (length1 = 0; base[length1] != '\\0'; length1++)
    ;
  for (length2 = 0; comp[length2] != '\\0'; length2++)
    ;
  if (length1 != length2)
    return false;

  for (int i = 0; base[i] != '\\0'; i++) {
    if (base[i] != comp[i])
      return false;
  }
  return true;
}

// 辞書順が等しい時は3,leftの方が早い場合は1,rightの方が早いときは2
int strCmp2(const char left[300], const char right[300]) {
  int i;

  if (strCmp(left, right))
    return 3;

  for (i = 0; left[i] != '\\0' && right[i] != '\\0'; i++) {
    if (left[i] != right[i]) {
      if (left[i] < right[i])
        return 1;
      else {
        return 2;
      }
    }
  }
  if (left[i] == '\\0')
    return 1;
  else {
    return 2;
  }
}

struct Edge {
  Edge(int arg_to, char arg_buf[7]) {
    to = arg_to;
    strcpy(buf, arg_buf);
    deleted = false;
  }
  int to;
  char buf[7];
  bool deleted;
};

struct Data {
  Data(int arg_node_id, int arg_edge_id) {
    node_id = arg_node_id;
    edge_id = arg_edge_id;
  }
  int node_id;
  int edge_id;
};

struct Info {
  Info(int arg_node_id, char arg_tmp_string[300]) {
    node_id = arg_node_id;
    strcpy(tmp_string, arg_tmp_string);
  }

  Info() { node_id = 0; }

  bool operator<(const struct Info &arg) const {
    int compare = strCmp2(tmp_string, arg.tmp_string);

    if (compare == 2) { // argの方が早い
      return true;      // PQなので逆
    } else {
      return false;
    }
  }
  int node_id;
  char tmp_string[300];
  vector<Data> LOG;
};

int N, E, start, goal;
int index_table[40];
char min_string[40][400][300]; // min_string[node_id][index][string]
vector<Edge> G[NUM];

void func() {

  for (int i = 0; i < N; i++)
    G[i].clear();

  int from, to;
  char buf[7];

  for (int i = 0; i < E; i++) {
    scanf("%d %d %s", &from, &to, buf);
    G[from].push_back(Edge(to, buf));
  }

  int compare;

  // エッジを削る(同じノードかつ同じ行先)
  for (int i = 0; i < N; i++) {
    for (int k = 0; k + 1 < G[i].size(); k++) {
      if (G[i][k].deleted)
        continue;
      for (int p = k + 1; p < G[i].size(); p++) {
        if (G[i][k].to != G[i][p].to)
          continue;
        if (G[i][k].buf[0] == G[i][p].buf[0])
          continue; // 片方がもう片方に含まれる場合はSKIP

        compare = strCmp2(G[i][k].buf, G[i][p].buf);

        if (compare == 1) {
          G[i][p].deleted = true;
        } else {
          G[i][k].deleted = true;
        }
      }
    }
  }

  // 長い文字列を記録
  for (int i = 0; i < N; i++) {
    index_table[i] = 0; // いくつ接尾辞を持っているか
    for (int id = 0; id < 400; id++) {
      for (int k = 0; k < 250; k++) {
        min_string[i][id][k] = 'z';
      }
      min_string[i][id][250] = '\\0';
    }
  }

  min_string[start][0][0] = '\\0';

  priority_queue<Info> Q;
  char first_string[300];
  first_string[0] = '\\0';

  Q.push(Info(start, first_string));
  int next_node, next_length;
  char ans[300], work[300];

  // int debug = 0;

  vector<Data> ans_LOG;

  while (!Q.empty()) {

    if (Q.top().node_id == goal) {

      strcpy2(ans, Q.top().tmp_string);
      for (int i = 0; i < Q.top().LOG.size(); i++)
        ans_LOG.push_back(Q.top().LOG[i]);
      break; // 文字列の小さい順にPQを回しているので、最速解は最速に辿り着くはず<★最後のエッジの文字列が追加された状態でPQが回るから★>
    } else {

      for (int i = 0; i < G[Q.top().node_id].size(); i++) {
        if (G[Q.top().node_id][i].deleted)
          continue;
        next_node = G[Q.top().node_id][i].to;
        if (next_node == Q.top().node_id)
          continue; // 自己ループは無視

        // 新しい文字列を作る
        work[0] = '\\0';
        strcpy2(work, Q.top().tmp_string);
        // printf("work:%s tmp_str:%s\\n",work,Q.top().tmp_string);
        addcpy(work, G[Q.top().node_id][i].buf);
        // printf("work:%s buf:%s\\n",work,G[Q.top().node_id][i].buf);

        if (min_string[next_node][0][0] < work[0])
          continue;

        if (min_string[next_node][0][0] > work[0]) { // 過去最速

          strcpy(min_string[next_node][0], work);
          index_table[next_node] = 1;

        } else { // pre_fixが同点
          if (index_table[next_node] == E)
            continue; // あるノードへ到着する最小パターンは、多分エッジの総数より少ない

          strcpy(min_string[next_node][index_table[next_node]++],
                 work); // 最小値配列に追加
        }

        Info next_info;
        next_info.node_id = next_node;
        strcpy(next_info.tmp_string, work);
        for (int k = 0; k < Q.top().LOG.size(); k++)
          next_info.LOG.push_back(Q.top().LOG[k]);
        next_info.LOG.push_back(Data(Q.top().node_id, i));

        Q.push(next_info);
      }
      Q.pop();
    }
  }

  if (ans_LOG.size() == 0) {
    printf("NO\\n");
    return;
  }

  for (int i = 0; i < ans_LOG.size(); i++) {
    int node_id = ans_LOG[i].node_id;
    int edge_id = ans_LOG[i].edge_id;
    for (int k = 0; k < G[node_id].size(); k++) {
      if (G[node_id][k].to == node_id) { // 自己ループの辺
        if (strCmp2(G[node_id][k].buf, G[node_id][edge_id].buf) == 1) {
          printf("NO\\n"); // 最短経路をより短くする自己ループがあったらアウト
          return;
        }
      }
    }
  }

  printf("%s\\n", ans);
}

int main() {

  while (true) {
    scanf("%d %d %d %d", &N, &E, &start, &goal);
    if (N == 0 && E == 0 && start == 0 && goal == 0)
      break;

    func();
  }

  return 0;
}