#include <bits/stdc++.h>
#pragma comment(linker, "/STACK:65777216")
using namespace std;
int n;
int f[111111];
int s[111111];
vector<int> v[111111];
vector<pair<int, int> > res;
bool forb;
int f_a, f_b, f_c;
bool u[111111];
void dfs(int ver, int par = -1) {
  if (u[ver]) return;
  u[ver] = true;
  for (int i(0); i < (v[ver].size()); i++) {
    if (v[ver][i] == par) continue;
    if (u[v[ver][i]] && !forb) {
      forb = true;
      f_a = par;
      f_b = ver;
      f_c = v[ver][i];
    }
    dfs(v[ver][i], ver);
  }
}
int G_TYPE;
bool w[111111][2][2];
pair<int, int> R[111111][2][2];
int c[111111][2][2];
pair<int, int> solve(int ver, int take, int par) {
  if (w[ver][take][G_TYPE]) return R[ver][take][G_TYPE];
  vector<pair<int, int> > v1, v2;
  vector<int> vv;
  for (int i(0); i < (v[ver].size()); i++) {
    if (v[ver][i] == par) continue;
    if (forb && G_TYPE == 0 &&
        (ver == f_a && v[ver][i] == f_b || ver == f_b && v[ver][i] == f_a))
      continue;
    if (forb && G_TYPE == 1 &&
        (ver == f_c && v[ver][i] == f_b || ver == f_b && v[ver][i] == f_c))
      continue;
    pair<int, int> t1 = solve(v[ver][i], 0, ver);
    pair<int, int> t2 = solve(v[ver][i], 1, ver);
    v1.push_back(t1);
    v2.push_back(t2);
    vv.push_back(v[ver][i]);
  }
  pair<int, int> r;
  for (int i(0); i < (v1.size()); i++) {
    pair<int, int> t1 = v1[i];
    pair<int, int> t2 = v2[i];
    if (t1.first > t2.first || t1.first == t2.first && t1.second >= t2.second) {
      r.first += t1.first;
      r.second += t1.second;
    } else {
      r.first += t2.first;
      r.second += t2.second;
    }
  }
  if (take == 0) {
    return w[ver][take][G_TYPE] = 1, R[ver][take][G_TYPE] = r;
  } else {
    pair<int, int> best = r;
    for (int i(0); i < (vv.size()); i++) {
      int nver = vv[i];
      pair<int, int> t1 = v1[i];
      pair<int, int> t2 = v2[i];
      pair<int, int> t = r;
      if (t1.first > t2.first ||
          t1.first == t2.first && t1.second >= t2.second) {
        t.first -= t1.first;
        t.second -= t1.second;
      } else {
        t.first -= t2.first;
        t.second -= t2.second;
      }
      t.first += t1.first;
      t.second += t1.second;
      t.first++;
      if (s[ver] != s[nver]) t.second++;
      if (t.first > best.first ||
          t.first == best.first && t.second > best.second) {
        best = t;
        c[ver][take][G_TYPE] = nver;
      }
    }
    return w[ver][take][G_TYPE] = 1, R[ver][take][G_TYPE] = best;
  }
}
pair<int, int> solve(int ver, int type) {
  G_TYPE = type;
  pair<int, int> t1 = solve(ver, 0, -1);
  pair<int, int> t2 = solve(ver, 1, -1);
  if (t1.first > t2.first || t1.first == t2.first && t1.second >= t2.second)
    return t1;
  return t2;
}
void add(int ver, int take, int par) {
  if (take && c[ver][take][G_TYPE] != -1)
    res.push_back(pair<int, int>(ver, c[ver][take][G_TYPE]));
  for (int i(0); i < (v[ver].size()); i++) {
    if (v[ver][i] == par) continue;
    if (forb && G_TYPE == 0 &&
        (ver == f_a && v[ver][i] == f_b || ver == f_b && v[ver][i] == f_a))
      continue;
    if (forb && G_TYPE == 1 &&
        (ver == f_c && v[ver][i] == f_b || ver == f_b && v[ver][i] == f_c))
      continue;
    if (take && c[ver][take][G_TYPE] == v[ver][i]) {
      add(v[ver][i], 0, ver);
    } else {
      pair<int, int> t1 = solve(v[ver][i], 0, ver);
      pair<int, int> t2 = solve(v[ver][i], 1, ver);
      if (t1.first > t2.first ||
          t1.first == t2.first && t1.second >= t2.second) {
        add(v[ver][i], 0, ver);
      } else {
        add(v[ver][i], 1, ver);
      }
    }
  }
}
void add(int ver, int type) {
  G_TYPE = type;
  pair<int, int> t1 = solve(ver, 0, -1);
  pair<int, int> t2 = solve(ver, 1, -1);
  if (t1.first > t2.first || t1.first == t2.first && t1.second >= t2.second)
    add(ver, 0, -1);
  else
    add(ver, 1, -1);
}
int main() {
  memset(c, -1, sizeof(c));
  cin >> n;
  for (int i(0); i < (n); i++) {
    scanf("%d %d", f + i, s + i);
    f[i]--;
    v[i].push_back(f[i]);
    v[f[i]].push_back(i);
  }
  for (int i(0); i < (n); i++)
    if (v[i].size() > 1) {
      if (v[i].size() == 2) {
        if (v[i][0] == v[i][1]) {
          v[i].pop_back();
        }
        continue;
      }
      sort((v[i]).begin(), (v[i]).end()),
          v[i].erase(unique(v[i].begin(), v[i].end()), v[i].end());
    }
  int curr_t = 0, curr_e = 0;
  for (int i(0); i < (n); i++)
    if (!u[i]) {
      forb = 0;
      dfs(i);
      pair<int, int> r;
      if (!forb) {
        r = solve(i, 0);
        add(i, 0);
      } else {
        r = solve(i, 0);
        pair<int, int> r2 = solve(i, 1);
        if (r.first < r2.first || r.first == r2.first && r.second < r2.second) {
          r = r2;
          add(i, 1);
        } else
          add(i, 0);
      }
      curr_t += r.first;
      curr_e += r.second;
    }
  cout << curr_t << ' ' << curr_e << endl;
  for (int i(0); i < (res.size()); i++)
    printf("%d %d\n", res[i].first + 1, res[i].second + 1);
  return 0;
}
