Problem p02908 (C++)

Buggy submission (status: Time Limit Exceeded):
#include <bits/stdc++.h>

const int N = 100005, inf = 0x3f3f3f3f;

int n, s, t, p[N], q[N], L[N], R[N], head[N], dis[N], cur[N];
int left[N], right[N], tot = 1, idx;
bool vis[N];

struct edge {
  int to, nxt, rem;
} e[N * 10];

void link(int x, int y, int z, int w = 0) {
  e[++tot] = (edge){y, head[x], z}, head[x] = tot;
  e[++tot] = (edge){x, head[y], w}, head[y] = tot;
}

bool bfs() {
  std::memset(dis, 0, idx + 1 << 2);
  std::queue<int> q;
  q.push(s), dis[s] = 1;
  while (q.size()) {
    int tmp = q.front();
    q.pop();
    for (int i = head[tmp]; i; i = e[i].nxt)
      if (e[i].rem && !dis[e[i].to])
        dis[e[i].to] = dis[tmp] + 1, q.push(e[i].to);
  }
  return dis[t] > 0;
}
int dinic(int x, int low) {
  if (x == t || !low)
    return low;
  int ans = 0, t;
  for (int i = head[x]; i; i = e[i].nxt)
    if (e[i].rem && dis[e[i].to] == dis[x] + 1 &&
        (t = dinic(e[i].to, std::min(low, e[i].rem)))) {
      e[i].rem -= t, e[i ^ 1].rem += t, ans += t, low -= t;
      if (!low)
        break;
    }
  return ans;
}

int main() {
  std::ios::sync_with_stdio(0), std::cin.tie(0);
  std::cin >> n;
  for (int i = 0; i < n; ++i)
    std::cin >> p[i];
  for (int i = 0; i < n; ++i)
    std::cin >> q[i];
  for (int i = 0; i < n; ++i)
    if (!vis[i]) {
      ++idx;
      for (int j = i; !vis[j]; vis[j] = 1, j = p[j])
        L[j] = idx;
    }
  std::memset(vis, 0, sizeof vis);
  for (int i = 0; i < n; ++i)
    if (!vis[i]) {
      ++idx;
      for (int j = i; !vis[j]; vis[j] = 1, j = q[j])
        R[j] = idx;
    }
  t = ++idx;
  int ans = n;
  for (int i = 0; i < n; ++i)
    if (p[i] != i || q[i] != i) {
      if (p[i] == i) {
        ++left[R[i]];
      } else if (q[i] == i) {
        ++right[L[i]];
      } else if (p[i] == q[i]) {
        link(L[i], R[i], 1, 1);
      } else {
        link(L[i], R[i], 1);
      }
    } else
      --ans;
  for (int i = 1; i < idx; ++i) {
    if (left[i])
      link(s, i, left[i]);
    if (right[i])
      link(i, t, right[i]);
  }
  while (bfs())
    std::memcpy(cur, head, idx + 1 << 2), ans -= dinic(s, inf);
  std::cout << ans << '\n';
  return 0;
}

Fixed submission:
#include <bits/stdc++.h>

const int N = 100005, inf = 0x3f3f3f3f;

int n, s, t, p[N], q[N], L[N], R[N], head[N], dis[N], cur[N];
int left[N], right[N], tot = 1, idx;
bool vis[N];

struct edge {
  int to, nxt, rem;
} e[N * 10];

void link(int x, int y, int z, int w = 0) {
  e[++tot] = (edge){y, head[x], z}, head[x] = tot;
  e[++tot] = (edge){x, head[y], w}, head[y] = tot;
}

bool bfs() {
  std::memset(dis, 0, idx + 1 << 2);
  std::queue<int> q;
  q.push(s), dis[s] = 1;
  while (q.size()) {
    int tmp = q.front();
    q.pop();
    for (int i = head[tmp]; i; i = e[i].nxt)
      if (e[i].rem && !dis[e[i].to])
        dis[e[i].to] = dis[tmp] + 1, q.push(e[i].to);
  }
  return dis[t] > 0;
}
int dinic(int x, int low) {
  if (x == t || !low)
    return low;
  int ans = 0, t;
  for (int &i = cur[x]; i; i = e[i].nxt)
    if (e[i].rem && dis[e[i].to] == dis[x] + 1 &&
        (t = dinic(e[i].to, std::min(low, e[i].rem)))) {
      e[i].rem -= t, e[i ^ 1].rem += t, ans += t, low -= t;
      if (!low)
        break;
    }
  return ans;
}

int main() {
  std::ios::sync_with_stdio(0), std::cin.tie(0);
  std::cin >> n;
  for (int i = 0; i < n; ++i)
    std::cin >> p[i];
  for (int i = 0; i < n; ++i)
    std::cin >> q[i];
  for (int i = 0; i < n; ++i)
    if (!vis[i]) {
      ++idx;
      for (int j = i; !vis[j]; vis[j] = 1, j = p[j])
        L[j] = idx;
    }
  std::memset(vis, 0, sizeof vis);
  for (int i = 0; i < n; ++i)
    if (!vis[i]) {
      ++idx;
      for (int j = i; !vis[j]; vis[j] = 1, j = q[j])
        R[j] = idx;
    }
  t = ++idx;
  int ans = n;
  for (int i = 0; i < n; ++i)
    if (p[i] != i || q[i] != i) {
      if (p[i] == i) {
        ++left[R[i]];
      } else if (q[i] == i) {
        ++right[L[i]];
      } else if (p[i] == q[i]) {
        link(L[i], R[i], 1, 1);
      } else {
        link(L[i], R[i], 1);
      }
    } else
      --ans;
  for (int i = 1; i < idx; ++i) {
    if (left[i])
      link(s, i, left[i]);
    if (right[i])
      link(i, t, right[i]);
  }
  while (bfs())
    std::memcpy(cur, head, idx + 1 << 2), ans -= dinic(s, inf);
  std::cout << ans << '\n';
  return 0;
}