Problem p01632 (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 300

enum Type {
  IN,
  OUT,
};

// 辺を表す構造体(行先、容量、逆辺のインデックス)
struct Edge {
  Edge(int arg_to, int arg_capacity, int arg_rev_index) {
    to = arg_to;
    capacity = arg_capacity;
    rev_index = arg_rev_index;
  }
  int to, capacity, rev_index;
};

struct Info {
  int from, to;
};

int V;

vector<Edge> G[NUM];   // グラフの隣接リスト表現
int dist[NUM];         // sourceからの距離
int cheked_index[NUM]; // どこまで調べ終わったか
Info info[6000];

// fromからtoへ向かう容量capacityの辺をグラフに追加する
void add_edge(int from, int to, int capacity) {
  G[from].push_back(Edge(to, capacity, G[to].size()));
  G[to].push_back(Edge(from, 0, G[from].size() - 1)); // 逆辺の、初期容量は0
}

// sourceからの最短距離をBFSで計算する
void bfs(int source) {
  for (int i = 0; i < V; i++)
    dist[i] = -1;
  queue<int> Q;
  dist[source] = 0;
  Q.push(source);

  while (!Q.empty()) {
    int node_id = Q.front();
    Q.pop();
    for (int i = 0; i < G[node_id].size(); i++) {
      Edge &e = G[node_id][i];
      if (e.capacity > 0 &&
          dist[e.to] < 0) { // 辺の容量が正で、かつエッジの行先に未訪問の場合
        dist[e.to] = dist[node_id] + 1;
        Q.push(e.to);
      }
    }
  }
}

// 増加パスをDFSで探す
int dfs(int node_id, int sink, int flow) {
  if (node_id == sink)
    return flow; // 終点についたらflowをreturn

  for (int &i = cheked_index[node_id]; i < G[node_id].size();
       i++) { // node_idから出ているエッジを調査
    Edge &e = G[node_id][i];
    if (e.capacity > 0 &&
        dist[node_id] <
            dist[e.to]) { // 流せる余裕があり、かつsourceからの距離が増加する方法である場合
      int tmp_flow = dfs(e.to, sink, min(flow, e.capacity)); // 流せるだけ流す
      if (tmp_flow > 0) {                                    // 流せた場合
        e.capacity -= tmp_flow; // 流した分、エッジの容量を削減する
        G[e.to][e.rev_index].capacity +=
            tmp_flow; // 逆辺の容量を、流した分だけ増加させる
        return tmp_flow;
      }
    }
  }
  return 0;
}

// sourceからsinkへの最大流を求める
int max_flow(int source, int sink) { // source:始点 sink:終点
  int flow = 0, add;
  while (true) { // 増加パスが存在する限り、流量を追加し続ける
    bfs(source);
    if (dist[sink] < 0)
      break; // sourceからsinkへと辿り着く残余グラフがない、つまり増加パスが無くなった場合、break
    for (int i = 0; i < V; i++)
      cheked_index[i] = 0;
    while ((add = dfs(source, sink, BIG_NUM)) >
           0) { // 増加パスが見つかる間、加算
      flow += add;
    }
  }
  return flow;
}

int main() {

  int N, M;
  scanf("%d %d", &N, &M);

  int source = 0, sink = 2 * N;
  int index_table[100][2];
  for (int i = 0; i < N; i++) {
    index_table[i][IN] = 2 * i;
    index_table[i][OUT] = 2 * i + 1;
  }

  V = 2 * N + 1;

  for (int i = 0; i < M; i++) {
    scanf("%d %d", &info[i].from, &info[i].to);
    info[i].from--;
    info[i].to--;

    if (i == 0) {
      printf("No\\n");
      continue;
    }

    for (int k = 0; k < NUM; k++)
      G[k].clear();

    add_edge(index_table[0][IN], index_table[0][OUT], 2); // 行きと帰りで流量2
    for (int k = 1; k < N; k++) {
      add_edge(index_table[k][IN], index_table[k][OUT],
               1); // 各町の入次ノードと出次ノードを結ぶ
    }

    // 辺を張りなおす
    for (int k = 0; k < i; k++) {
      add_edge(index_table[info[k].from][OUT], index_table[info[k].to][IN], 1);
      add_edge(index_table[info[k].to][OUT], index_table[info[k].from][IN], 1);
    }

    // 最新の辺は、その両端のノードをsinkへつなぐ
    add_edge(index_table[info[i].from][OUT], sink, 1);
    add_edge(index_table[info[i].to][OUT], sink, 1);

    if (max_flow(source, sink) == 2) {
      printf("Yes\\n");
    } else {
      printf("No\\n");
    }
  }

  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 300

enum Type {
  IN,
  OUT,
};

// 辺を表す構造体(行先、容量、逆辺のインデックス)
struct Edge {
  Edge(int arg_to, int arg_capacity, int arg_rev_index) {
    to = arg_to;
    capacity = arg_capacity;
    rev_index = arg_rev_index;
  }
  int to, capacity, rev_index;
};

struct Info {
  int from, to;
};

int V;

vector<Edge> G[NUM];   // グラフの隣接リスト表現
int dist[NUM];         // sourceからの距離
int cheked_index[NUM]; // どこまで調べ終わったか
Info info[100];

// fromからtoへ向かう容量capacityの辺をグラフに追加する
void add_edge(int from, int to, int capacity) {
  G[from].push_back(Edge(to, capacity, G[to].size()));
  G[to].push_back(Edge(from, 0, G[from].size() - 1)); // 逆辺の、初期容量は0
}

// sourceからの最短距離をBFSで計算する
void bfs(int source) {
  for (int i = 0; i < V; i++)
    dist[i] = -1;
  queue<int> Q;
  dist[source] = 0;
  Q.push(source);

  while (!Q.empty()) {
    int node_id = Q.front();
    Q.pop();
    for (int i = 0; i < G[node_id].size(); i++) {
      Edge &e = G[node_id][i];
      if (e.capacity > 0 &&
          dist[e.to] < 0) { // 辺の容量が正で、かつエッジの行先に未訪問の場合
        dist[e.to] = dist[node_id] + 1;
        Q.push(e.to);
      }
    }
  }
}

// 増加パスをDFSで探す
int dfs(int node_id, int sink, int flow) {
  if (node_id == sink)
    return flow; // 終点についたらflowをreturn

  for (int &i = cheked_index[node_id]; i < G[node_id].size();
       i++) { // node_idから出ているエッジを調査
    Edge &e = G[node_id][i];
    if (e.capacity > 0 &&
        dist[node_id] <
            dist[e.to]) { // 流せる余裕があり、かつsourceからの距離が増加する方法である場合
      int tmp_flow = dfs(e.to, sink, min(flow, e.capacity)); // 流せるだけ流す
      if (tmp_flow > 0) {                                    // 流せた場合
        e.capacity -= tmp_flow; // 流した分、エッジの容量を削減する
        G[e.to][e.rev_index].capacity +=
            tmp_flow; // 逆辺の容量を、流した分だけ増加させる
        return tmp_flow;
      }
    }
  }
  return 0;
}

// sourceからsinkへの最大流を求める
int max_flow(int source, int sink) { // source:始点 sink:終点
  int flow = 0, add;
  while (true) { // 増加パスが存在する限り、流量を追加し続ける
    bfs(source);
    if (dist[sink] < 0)
      break; // sourceからsinkへと辿り着く残余グラフがない、つまり増加パスが無くなった場合、break
    for (int i = 0; i < V; i++)
      cheked_index[i] = 0;
    while ((add = dfs(source, sink, BIG_NUM)) >
           0) { // 増加パスが見つかる間、加算
      flow += add;
    }
  }
  return flow;
}

int main() {

  int N, M;
  scanf("%d %d", &N, &M);

  int source = 0, sink = 2 * N;
  int index_table[100][2];
  for (int i = 0; i < N; i++) {
    index_table[i][IN] = 2 * i;
    index_table[i][OUT] = 2 * i + 1;
  }

  V = 2 * N + 1;

  for (int i = 0; i < M; i++) {
    scanf("%d %d", &info[i].from, &info[i].to);
    info[i].from--;
    info[i].to--;

    if (i == 0) {
      printf("No\\n");
      continue;
    }

    for (int k = 0; k < NUM; k++)
      G[k].clear();

    add_edge(index_table[0][IN], index_table[0][OUT], 2); // 行きと帰りで流量2
    for (int k = 1; k < N; k++) {
      add_edge(index_table[k][IN], index_table[k][OUT],
               1); // 各町の入次ノードと出次ノードを結ぶ
    }

    // 辺を張りなおす
    for (int k = 0; k < i; k++) {
      add_edge(index_table[info[k].from][OUT], index_table[info[k].to][IN], 1);
      add_edge(index_table[info[k].to][OUT], index_table[info[k].from][IN], 1);
    }

    // 最新の辺は、その両端のノードをsinkへつなぐ
    add_edge(index_table[info[i].from][OUT], sink, 1);
    add_edge(index_table[info[i].to][OUT], sink, 1);

    if (max_flow(source, sink) == 2) {
      printf("Yes\\n");
    } else {
      printf("No\\n");
    }
  }

  return 0;
}