Problem p02942 (C++)

Buggy submission (status: Runtime Error):
/*

  _|_|                              _|  _|    _|
_|    _|  _|  _|_|  _|_|_|_|        _|  _|  _|
_|    _|  _|_|          _|          _|  _|_|
_|    _|  _|          _|      _|    _|  _|  _|
  _|_|    _|        _|_|_|_|    _|_|    _|    _|

*/
#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <queue>
#include <set>
#include <vector>
// #define ls (rt<<1)
// #define rs (rt<<1|1)
#define vi vector<int>
#define pb push_back
#define mk make_pair
#define pii pair<int, int>
#define rep(i, a, b) for (int i = (a), i##end = (b); i <= i##end; i++)
#define fi first
#define se second
typedef long long ll;
using namespace std;
const int maxn =
    205; // 1~n 为颜色点 n+1~2*n为行点 所有没到过的格子给行->颜色连一条边
         // 跑完后，每个颜色新增的哪个行，标记打上，然后在B里放入这个。
const int inf = 1e9;
struct Flow {
  int s, t, head[maxn], cur[maxn], cnt, q[maxn], rk[maxn];
  struct gg {
    int u, v, w, next;
  } side[maxn * 2];
  Flow() { s = maxn - 3, t = maxn - 2, cnt = 1; }
  void reset() {
    cnt = 1;
    memset(head, 0, sizeof(head));
  }
  void ins(int u, int v) {
    side[++cnt] = (gg){u, v, 1, head[u]};
    head[u] = cnt;
    side[++cnt] = (gg){v, u, 0, head[v]};
    head[v] = cnt;
  }
  bool bfs() {
    memset(rk, 0, sizeof(rk));
    int hd = 1, tl = 1;
    q[tl] = s;
    rk[s] = 1;
    while (hd <= tl) {
      int u = q[hd++];
      for (int i = head[u]; i; i = side[i].next) {
        int v = side[i].v;
        if (rk[v] || !side[i].w)
          continue;
        rk[v] = rk[u] + 1;
        q[++tl] = v;
      }
    }
    return rk[t];
  }
  int dfs(int u, int flow) {
    if (u == t)
      return flow;
    int tot = 0;
    for (int &i = cur[u]; i; i = side[i].next) {
      int v = side[i].v;
      if (rk[u] + 1 != rk[v] || !side[i].w)
        continue;
      int sent = dfs(v, min(flow, side[i].w));
      flow -= sent;
      tot += sent;
      side[i].w -= sent;
      side[i ^ 1].w += sent;
    }
    return tot;
  }
  void dinic() {
    int maxflow = 0;
    while (bfs()) {
      memcpy(cur, head, sizeof(head));
      maxflow += dfs(s, inf);
    }
  }
} f;
int A[105][105], B[105][105], C[105][105], col[105][105]; // col=属于哪一行
bool used[105][105];
int n, m;
int get_col(int num) {
  int tmp = num % m;
  if (!tmp)
    tmp = m;
  return (num - tmp) / m + 1;
}
int main() {
  scanf("%d%d", &n, &m);
  rep(i, 1, n) rep(j, 1, m) scanf("%d", &A[i][j]), col[i][j] = get_col(A[i][j]);
  rep(floor, 1, m) {
    f.reset();
    rep(i, 1, n) f.ins(f.s, i), f.ins(i + n, f.t);
    rep(i, 1, n) rep(j, 1, m) if (!used[i][j]) f.ins(col[i][j], i + n);
    f.dinic();
    rep(i, n + 1, 2 * n) { // 枚举每一行
      for (int j = f.head[i]; j; j = f.side[j].next) {
        int v = f.side[j].v;
        if (v <= n && f.side[j].w) { // 颜色v->行i-n的匹配被点亮
          rep(k, 1, m) {             // 寻找这一行中符合这一颜色的
            if (col[i - n][k] == v && !used[i - n][k]) {
              used[i - n][k] = 1;
              B[i - n][floor] = A[i - n][k]; // 填过来
              break;
            }
          }
          break;
        }
      }
    }
  }
  // 现在B中每一列的任意一种颜色只有一个
  rep(i, 1, n) rep(j, 1, m) C[get_col(B[i][j])][j] = B[i][j];
  rep(i, 1, n) {
    rep(j, 1, m) printf("%d ", B[i][j]);
    printf("\n");
  }
  rep(i, 1, n) {
    rep(j, 1, m) printf("%d ", C[i][j]);
    printf("\n");
  }
  return 0;
}

Fixed submission:
/*

  _|_|                              _|  _|    _|
_|    _|  _|  _|_|  _|_|_|_|        _|  _|  _|
_|    _|  _|_|          _|          _|  _|_|
_|    _|  _|          _|      _|    _|  _|  _|
  _|_|    _|        _|_|_|_|    _|_|    _|    _|

*/
#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <queue>
#include <set>
#include <vector>
// #define ls (rt<<1)
// #define rs (rt<<1|1)
#define vi vector<int>
#define pb push_back
#define mk make_pair
#define pii pair<int, int>
#define rep(i, a, b) for (int i = (a), i##end = (b); i <= i##end; i++)
#define fi first
#define se second
typedef long long ll;
using namespace std;
const int maxn =
    105 * 105 +
    2 * 105; // 1~n 为颜色点 n+1~2*n为行点 所有没到过的格子给行->颜色连一条边
             // 跑完后，每个颜色新增的哪个行，标记打上，然后在B里放入这个。
const int inf = 1e9;
struct Flow {
  int s, t, head[maxn], cur[maxn], cnt, q[maxn], rk[maxn];
  struct gg {
    int u, v, w, next;
  } side[maxn * 2];
  Flow() { s = maxn - 3, t = maxn - 2, cnt = 1; }
  void reset() {
    cnt = 1;
    memset(head, 0, sizeof(head));
  }
  void ins(int u, int v) {
    side[++cnt] = (gg){u, v, 1, head[u]};
    head[u] = cnt;
    side[++cnt] = (gg){v, u, 0, head[v]};
    head[v] = cnt;
  }
  bool bfs() {
    memset(rk, 0, sizeof(rk));
    int hd = 1, tl = 1;
    q[tl] = s;
    rk[s] = 1;
    while (hd <= tl) {
      int u = q[hd++];
      for (int i = head[u]; i; i = side[i].next) {
        int v = side[i].v;
        if (rk[v] || !side[i].w)
          continue;
        rk[v] = rk[u] + 1;
        q[++tl] = v;
      }
    }
    return rk[t];
  }
  int dfs(int u, int flow) {
    if (u == t)
      return flow;
    int tot = 0;
    for (int &i = cur[u]; i; i = side[i].next) {
      int v = side[i].v;
      if (rk[u] + 1 != rk[v] || !side[i].w)
        continue;
      int sent = dfs(v, min(flow, side[i].w));
      flow -= sent;
      tot += sent;
      side[i].w -= sent;
      side[i ^ 1].w += sent;
    }
    return tot;
  }
  void dinic() {
    int maxflow = 0;
    while (bfs()) {
      memcpy(cur, head, sizeof(head));
      maxflow += dfs(s, inf);
    }
  }
} f;
int A[105][105], B[105][105], C[105][105], col[105][105]; // col=属于哪一行
bool used[105][105];
int n, m;
int get_col(int num) {
  int tmp = num % m;
  if (!tmp)
    tmp = m;
  return (num - tmp) / m + 1;
}
int main() {
  scanf("%d%d", &n, &m);
  rep(i, 1, n) rep(j, 1, m) scanf("%d", &A[i][j]), col[i][j] = get_col(A[i][j]);
  rep(floor, 1, m) {
    f.reset();
    rep(i, 1, n) f.ins(f.s, i), f.ins(i + n, f.t);
    rep(i, 1, n) rep(j, 1, m) if (!used[i][j]) f.ins(col[i][j], i + n);
    f.dinic();
    rep(i, n + 1, 2 * n) { // 枚举每一行
      for (int j = f.head[i]; j; j = f.side[j].next) {
        int v = f.side[j].v;
        if (v <= n && f.side[j].w) { // 颜色v->行i-n的匹配被点亮
          rep(k, 1, m) {             // 寻找这一行中符合这一颜色的
            if (col[i - n][k] == v && !used[i - n][k]) {
              used[i - n][k] = 1;
              B[i - n][floor] = A[i - n][k]; // 填过来
              break;
            }
          }
          break;
        }
      }
    }
  }
  // 现在B中每一列的任意一种颜色只有一个
  rep(i, 1, n) rep(j, 1, m) C[get_col(B[i][j])][j] = B[i][j];
  rep(i, 1, n) {
    rep(j, 1, m) printf("%d ", B[i][j]);
    printf("\n");
  }
  rep(i, 1, n) {
    rep(j, 1, m) printf("%d ", C[i][j]);
    printf("\n");
  }
  return 0;
}