#include <bits/stdc++.h>
#pragma comment(linker, "/STACK:16777216")
using namespace std;
inline pair<int, int> operator+=(pair<int, int> &a, const pair<int, int> &b) {
  a.first += b.first;
  a.second += b.second;
  return a;
}
inline pair<int, int> operator+(const pair<int, int> &a,
                                const pair<int, int> &b) {
  return pair<int, int>(a.first + b.first, a.second + b.second);
}
inline pair<int, int> operator-(const pair<int, int> &a,
                                const pair<int, int> &b) {
  return pair<int, int>(a.first - b.first, a.second - b.second);
}
int a, b, c, d, i, j, n, m, k;
int p[100001], pr[2][100001];
pair<int, int> dp[2][100001];
bool inCycle[100001], used[100001], boy[100001], take[100001];
vector<int> cycle[100001], sm[100001];
pair<int, int> ans;
vector<pair<int, int> > match;
pair<int, int> rec(int v, bool can) {
  if (dp[can][v] != make_pair(-1, -1)) return dp[can][v];
  pair<int, int> ans = make_pair(0, 0);
  pair<int, int> sum = make_pair(0, 0);
  for (int _n(((int)((sm[v]).size())) - 1), i(0); i <= _n; i++)
    if (!inCycle[sm[v][i]]) {
      pair<int, int> r = rec(sm[v][i], 1);
      sum += r;
    }
  if (sum > ans) {
    ans = sum;
    pr[can][v] = -1;
  }
  if (can)
    for (int _n(((int)((sm[v]).size())) - 1), i(0); i <= _n; i++) {
      if (inCycle[sm[v][i]]) continue;
      pair<int, int> r = sum - rec(sm[v][i], 1) + rec(sm[v][i], 0) +
                         make_pair(1, boy[v] != boy[sm[v][i]]);
      if (r > ans) {
        ans = r;
        pr[can][v] = sm[v][i];
      }
    }
  return dp[can][v] = ans;
}
void build(int v, bool can) {
  for (int _n(((int)((sm[v]).size())) - 1), i(0); i <= _n; i++)
    if (!inCycle[sm[v][i]]) {
      if (sm[v][i] != pr[can][v]) build(sm[v][i], 1);
    }
  if (pr[can][v] != -1) {
    build(pr[can][v], 0);
    match.push_back(make_pair(v, pr[can][v]));
  }
}
int main() {
  scanf("%d", &n);
  for (int _n((n)-1), i(0); i <= _n; i++)
    scanf("%d%d", &p[i], &b), --p[i], sm[p[i]].push_back(i), boy[i] = b - 1;
  for (int _n((n)-1), i(0); i <= _n; i++) {
    if (used[i]) continue;
    vector<int> cur(0), o(0);
    a = i;
    while (!used[a]) {
      cur.push_back(a);
      used[a] = 1;
      a = p[a];
    }
    while (!cur.empty() && cur.back() != a)
      o.push_back(cur.back()), cur.pop_back();
    if ((int)((cur).size()) && cur.back() == a) {
      cur.pop_back();
      o.push_back(a);
      for (int _n(((int)((o).size())) - 1), i(0); i <= _n; i++)
        inCycle[o[i]] = 1;
      cycle[m++] = o;
    }
  }
  memset(dp, -1, sizeof(dp));
  memset(pr, -1, sizeof(pr));
  for (int _n((m)-1), h(0); h <= _n; h++) {
    vector<bool> old;
    pair<int, int> best = make_pair(0, 0);
    bool fl = 0;
    for (int _n((2) - 1), firstLast(0); firstLast <= _n; firstLast++) {
      vector<pair<int, int> > dp_1((int)((cycle[h]).size()));
      vector<bool> pr_1((int)((cycle[h]).size()), false);
      for (int _n(((int)((cycle[h]).size())) - 1), i(0); i <= _n; i++) {
        bool can = 1;
        if (firstLast && (!i || i == (int)((cycle[h]).size()) - 1)) can = 0;
        dp_1[i] = rec(cycle[h][i], can);
        if (i) dp_1[i] += dp_1[i - 1];
        if (i &&
            (!firstLast || (i != (int)((cycle[h]).size()) - 1 && i != 1))) {
          pair<int, int> r = rec(cycle[h][i], 0);
          r += rec(cycle[h][i - 1], 0);
          r += make_pair(1, boy[cycle[h][i]] != boy[cycle[h][i - 1]]);
          if (i > 1) r += dp_1[i - 2];
          if (r > dp_1[i]) {
            dp_1[i] = r;
            pr_1[i] = 1;
          }
        }
      }
      pair<int, int> now = dp_1.back();
      if (firstLast)
        now += make_pair(1, boy[cycle[h][0]] != boy[cycle[h].back()]);
      if ((int)((old).size()) == 0 || now > best) {
        best = now;
        old = pr_1;
        fl = firstLast;
      }
    }
    ans += best;
    a = (int)((cycle[h]).size()) - 1;
    while (a >= 0) {
      bool cur = old[a] ^ 1;
      if (a == (int)((cycle[h]).size()) - 1 && fl) cur = 0;
      if (!a && fl) cur = 0;
      build(cycle[h][a], cur);
      if (old[a]) {
        build(cycle[h][a - 1], 0);
        match.push_back(make_pair(cycle[h][a], cycle[h][a - 1]));
        a -= 2;
      } else
        --a;
    }
    if (fl) match.push_back(make_pair(cycle[h][0], cycle[h].back()));
  }
  printf("%d %d\n", ans.first, ans.second);
  for (int _n(((int)((match).size())) - 1), i(0); i <= _n; i++) {
    printf("%d %d\n", match[i].first + 1, match[i].second + 1);
  }
}
