#include <bits/stdc++.h>
using namespace std;
const int N = 100100;
const pair<int, int> inf = make_pair(-123456, -123456);
int n, m, cp = 0;
int hd[N], s[N], ot[N << 1], nt[N << 1];
int f[N], u[N], E[N], L;
pair<int, int> F[N], G[N], ans = make_pair(0, 0);
pair<int, int> operator+(const pair<int, int> &A, const pair<int, int> &B) {
  return make_pair(A.first + B.first, A.second + B.second);
}
pair<int, int> operator-(const pair<int, int> &A, const pair<int, int> &B) {
  return make_pair(A.first - B.first, A.second - B.second);
}
void add(const int x, const int y) { ot[++cp] = y, nt[cp] = hd[x], hd[x] = cp; }
void init() {
  scanf("%d", &n);
  for (int i = 1; i <= n; ++i) u[i] = hd[i] = 0, scanf("%d%d", &f[i], &s[i]);
  for (int i = 1; i <= n; ++i) add(f[i], i);
}
int c[N], b[N], len = 0;
pair<int, int> Q[N][2], A[N];
bool pre[N][2], pr[N];
void bfs(const int x) {
  b[1] = x;
  int h = 1, t = 1, now;
  for (; h <= t; ++h) {
    now = b[h];
    for (int i = hd[now]; i != 0; i = nt[i])
      if (u[ot[i]] != 2) b[++t] = ot[i], u[ot[i]] = 1;
  }
  pair<int, int> FF;
  for (h = t; h > 0; --h) {
    now = b[h];
    F[now] = G[now] = make_pair(0, 0);
    for (int i = hd[now]; i != 0; i = nt[i])
      if (u[ot[i]] != 2) G[now] = G[now] + max(F[ot[i]], G[ot[i]]);
    for (int i = hd[now]; i != 0; i = nt[i])
      if (u[ot[i]] != 2) {
        FF = G[now] - max(F[ot[i]], G[ot[i]]);
        FF = FF + G[ot[i]] + make_pair(1, s[now] != s[ot[i]]);
        if (FF > F[now]) F[now] = FF, E[now] = ot[i];
      }
  }
}
void dfs(const int x, int y) {
  if (y == 2) y = F[x] > G[x];
  if (y == 1) A[++L] = make_pair(E[x], x);
  for (int i = hd[x]; i != 0; i = nt[i])
    if (u[ot[i]] != 2) dfs(ot[i], (E[x] == ot[i] && y) ? 0 : 2);
}
pair<int, int> Gans(const bool U) {
  L = ans.first;
  if (!U)
    Q[2][1] = F[c[2]], Q[2][0] = G[c[2]], pr[2] = 0;
  else {
    Q[2][0] = inf;
    Q[2][1] = G[c[1]] + G[c[2]] + make_pair(1, s[c[1]] != s[c[2]]);
    pr[2] = 1;
  }
  if (len == 2) {
    if (U) {
      A[++L] = make_pair(c[1], c[2]);
      dfs(c[1], 0), dfs(c[2], 0);
      return Q[2][1];
    }
    dfs(c[1], 2), dfs(c[2], 2);
    return max(F[c[1]], G[c[1]]) + max(F[c[2]], G[c[2]]);
  }
  pair<int, int> T, Y;
  for (int i = 3; i <= len; ++i) {
    pr[i] = 0;
    Q[i][0] = G[c[i]] + max(Q[i - 1][1], Q[i - 1][0]);
    pre[i][1] = pre[i][0] = (Q[i - 1][1] > Q[i - 1][0]);
    Q[i][1] = F[c[i]] + max(Q[i - 1][1], Q[i - 1][0]);
    T = Q[i - 1][0] + G[c[i]] + make_pair(1, s[c[i]] != s[c[i - 1]]);
    if (T > Q[i][1]) Q[i][1] = T, pre[i][1] = 0, pr[i] = 1;
  }
  if (U) {
    dfs(c[1], 0);
    int now = (Q[len][1] > Q[len][0]);
    for (int i = len; i >= 2; --i) {
      if (now && pr[i]) {
        A[++L] = make_pair(c[i], c[i - 1]);
        dfs(c[i], 0);
      } else
        dfs(c[i], now);
      now = pre[i][now];
    }
    return max(Q[len][1], Q[len][0]);
  }
  T = max(F[c[1]], G[c[1]]) + max(Q[len][1], Q[len][0]);
  Y = Q[len][0] + G[c[1]] + make_pair(1, s[c[1]] != s[c[len]]);
  if (T > Y) {
    dfs(c[1], 2);
    int now = (Q[len][1] > Q[len][0]);
    for (int i = len; i >= 2; --i) {
      if (now && pr[i]) {
        A[++L] = make_pair(c[i], c[i - 1]);
        dfs(c[i], 0);
      } else
        dfs(c[i], now);
      now = pre[i][now];
    }
  } else {
    A[++L] = make_pair(c[1], c[len]);
    dfs(c[1], 0), dfs(c[len], 0);
    int now = pre[len][0];
    for (int i = len - 1; i >= 2; --i) {
      if (now && pr[i]) {
        A[++L] = make_pair(c[i], c[i - 1]);
        dfs(c[i], 0);
      } else
        dfs(c[i], now);
      now = pre[i][now];
    }
  }
  return max(T, Y);
}
void deal(int x) {
  for (len = 0; u[x] == 0; x = f[x]) u[x] = 1;
  int p = x;
  c[++len] = p;
  for (u[p] = 2, x = f[x]; x != p; x = f[x]) c[++len] = x, u[x] = 2;
  for (int i = 1; i <= len; ++i) bfs(c[i]);
  pair<int, int> T, Y;
  T = Gans(0), Y = Gans(1);
  if (T > Y) Gans(0);
  ans = ans + max(T, Y);
}
int main() {
  init();
  for (int i = 1; i <= n; ++i)
    if (u[i] == 0) deal(i);
  printf("%d %d\n", ans.first, ans.second);
  for (int i = 1; i <= ans.first; ++i)
    printf("%d %d\n", A[i].first, A[i].second);
  return 0;
}
