#include <bits/stdc++.h>
using namespace std;
const long long INF = 1ll << 62;
bool vis[100005], ban[100005 << 1];
long long f[2][100005][2], ans;
int now, out[100005][2], out_cnt;
int ecnt = 1, favo[100005], last[100005], s[100005], dfn[100005], low[100005],
    sta[100005], top, ring[100005], siz, in_ring[100005], timer, timer2,
    pos[2][100005];
struct edge {
  int next, to;
  long long val;
} e[100005 << 1];
void addedge(int a, int b, long long c) {
  e[++ecnt] = (edge){last[a], b, c};
  last[a] = ecnt;
}
void tarjan(int x, int from) {
  sta[++top] = x;
  dfn[x] = low[x] = ++timer;
  for (int i = last[x]; i; i = e[i].next) {
    if (i == from) continue;
    int y = e[i].to;
    if (dfn[y])
      (low[x]) > (dfn[y]) ? (low[x]) = (dfn[y]) : 0;
    else {
      tarjan(y, i ^ 1);
      (low[x]) > (low[y]) ? (low[x]) = (low[y]) : 0;
    }
  }
  if (low[x] == dfn[x]) {
    int to = top;
    while (sta[to] != x) to--;
    if (to == top)
      --top;
    else {
      while (to != top) ring[++siz] = sta[top--];
      ring[++siz] = sta[top--];
      ++timer2;
      for (int i = 1; i <= siz; i++) in_ring[ring[i]] = timer2;
    }
  }
}
void output(int x, int k, int fa) {
  if (k) {
    out[++out_cnt][0] = x;
    out[out_cnt][1] = pos[now][x];
  }
  for (int i = last[x]; i; i = e[i].next) {
    int y = e[i].to;
    if (y == fa || ban[i]) continue;
    if (y == pos[now][x] && k)
      output(y, 0, x);
    else {
      if (f[now][y][0] > f[now][y][1])
        output(y, 0, x);
      else
        output(y, 1, x);
    }
  }
}
void dp(int x, int fa) {
  memset(f[now][x], 0, sizeof(f[now][x]));
  long long tmp = -INF;
  int tmp_pos;
  for (int i = last[x]; i; i = e[i].next) {
    int y = e[i].to;
    if (y == fa || ban[i]) continue;
    dp(y, x);
    long long up = max(f[now][y][0], f[now][y][1]);
    f[now][x][0] += up;
    f[now][x][1] += up;
    if (tmp < f[now][y][0] - up + e[i].val) {
      tmp = f[now][y][0] - up + e[i].val;
      tmp_pos = y;
    }
  }
  f[now][x][1] += tmp;
  pos[now][x] = tmp_pos;
}
void solve(int x) {
  siz = 0;
  tarjan(x, 0);
  if (siz) {
    int p = ring[1], cnt = 0;
    long long tmp[3], b[3];
    for (int i = last[p]; i; i = e[i].next) {
      int y = e[i].to;
      if (in_ring[y]) {
        ++cnt;
        b[cnt] = i;
        ban[i] = ban[i ^ 1] = 1;
        now = cnt - 1;
        dp(x, 0);
        ban[i] = ban[i ^ 1] = 0;
        tmp[cnt] = max(f[now][x][1], f[now][x][0]);
        if (cnt == 2) break;
      }
    }
    if (tmp[1] > tmp[2]) {
      ban[b[1]] = ban[b[1] ^ 1] = 1;
      now = 0;
      if (f[now][x][0] > f[now][x][1])
        output(x, 0, 0);
      else
        output(x, 1, 0);
    } else {
      ban[b[2]] = ban[b[2] ^ 1] = 1;
      now = 1;
      if (f[now][x][0] > f[now][x][1])
        output(x, 0, 0);
      else
        output(x, 1, 0);
    }
    ans += max(tmp[1], tmp[2]);
  } else {
    now = 0;
    dp(x, 0);
    ans += max(f[now][x][1], f[now][x][0]);
    if (f[now][x][0] > f[now][x][1])
      output(x, 0, 0);
    else
      output(x, 1, 0);
  }
}
int main() {
  int n;
  scanf("%d", &n);
  for (int i = 1; i <= n; i++) {
    scanf("%d%d", &favo[i], &s[i]);
    s[i]--;
  }
  for (int i = 1; i <= n; i++) {
    int v = 100005 + (s[i] ^ s[favo[i]]);
    if (favo[i] == i) continue;
    addedge(i, favo[i], v);
    addedge(favo[i], i, v);
  }
  for (int i = 1; i <= n; i++)
    if (!dfn[i]) solve(i);
  printf("%d %d\n", (int)(ans / 100005), (int)(ans % 100005));
  for (int i = 1; i <= out_cnt; i++) printf("%d %d\n", out[i][0], out[i][1]);
}
