#include <bits/stdc++.h>
using namespace std;
int n;
const int N = 1e5 + 100;
int f[N], s[N];
vector<int> G[N], ve[N];
int fa[N], prevv[N];
pair<int, int> dp[N][2];
vector<pair<int, int> > pat;
int father(int x) { return fa[x] == x ? x : fa[x] = father(fa[x]); }
void unionn(int x, int y) { fa[father(x)] = father(y); }
map<int, int> mapa[N];
int used[N], ff;
pair<int, int> ans = make_pair(0, 0);
vector<int> cir;
bool dfs1(int x, int F) {
  used[x] = 1;
  for (map<int, int>::iterator it = mapa[x].begin(); it != mapa[x].end();
       it++) {
    int tmp = it->first;
    if (tmp == F && it->second == 1) continue;
    if (used[tmp]) {
      ff = tmp;
      cir.push_back(x);
      return true;
    }
    int tt = dfs1(tmp, x);
    if (tt) {
      if (ff) cir.push_back(x);
      if (ff == x) ff = 0;
      return 1;
    }
  }
  return 0;
}
void dfs2(int x, int F) {
  pair<int, int> tt = make_pair(0, 0);
  for (int i = 0; i < G[x].size(); i++) {
    int tmp = G[x][i];
    if (tmp == F) continue;
    dfs2(tmp, x);
    tt.first += dp[tmp][1].first;
    tt.second += dp[tmp][1].second;
  }
  dp[x][0] = dp[x][1] = tt;
  for (int i = 0; i < G[x].size(); i++) {
    int tmp = G[x][i];
    if (tmp == F) continue;
    pair<int, int> z =
        make_pair(tt.first - dp[tmp][1].first + dp[tmp][0].first + 1,
                  tt.second - dp[tmp][1].second + dp[tmp][0].second +
                      (s[tmp] != s[x] ? 1 : 0));
    if (z > dp[x][1]) {
      dp[x][1] = z;
      prevv[x] = tmp;
    }
  }
}
void dfs3(int x, int F, int p) {
  if (prevv[x] && p) {
    cout << prevv[x] << ' ' << x << endl;
    dfs3(prevv[x], x, 0);
  }
  for (int i = 0; i < G[x].size(); i++) {
    int tmp = G[x][i];
    if (tmp == F || tmp == prevv[x] && p) continue;
    dfs3(tmp, x, 1);
  }
}
int main() {
  cin >> n;
  for (int i = 1; i <= n; i++) fa[i] = i;
  for (int i = 1; i <= n; i++) {
    cin >> f[i] >> s[i];
    mapa[i][f[i]]++;
    mapa[f[i]][i]++;
    unionn(i, f[i]);
  }
  for (int i = 1; i <= n; i++) ve[father(i)].push_back(i);
  for (int i = 1; i <= n; i++)
    if (father(i) == i) {
      cir.clear();
      dfs1(i, 0);
      int u = cir[0], v = cir[1], w = cir.size() > 2 ? cir[2] : cir[0];
      mapa[u][v]--;
      mapa[v][u]--;
      vector<pair<int, int> > vv1, vv2;
      for (int j = 0; j < ve[i].size(); j++) {
        G[ve[i][j]].clear();
        for (map<int, int>::iterator it = mapa[ve[i][j]].begin();
             it != mapa[ve[i][j]].end(); it++) {
          if (it->second) G[ve[i][j]].push_back(it->first);
        }
      }
      dfs2(i, 0);
      pair<int, int> tans = dp[i][1];
      vector<int> tv;
      for (int j = 0; j < ve[i].size(); j++) tv.push_back(prevv[ve[i][j]]);
      for (int j = 0; j < ve[i].size(); j++) prevv[ve[i][j]] = 0;
      for (int j = 0; j < ve[i].size(); j++)
        dp[ve[i][j]][0] = dp[ve[i][j]][1] = make_pair(0, 0);
      mapa[u][v]++;
      mapa[v][u]++;
      mapa[v][w]--;
      mapa[w][v]--;
      for (int j = 0; j < ve[i].size(); j++) {
        G[ve[i][j]].clear();
        for (map<int, int>::iterator it = mapa[ve[i][j]].begin();
             it != mapa[ve[i][j]].end(); it++) {
          if (it->second) G[ve[i][j]].push_back(it->first);
        }
      }
      dfs2(i, 0);
      if (tans >= dp[i][1]) {
        ans.first += tans.first, ans.second += tans.second;
        for (int j = 0; j < ve[i].size(); j++) prevv[ve[i][j]] = tv[j];
        mapa[v][w]++, mapa[w][v]++;
        mapa[u][v]--, mapa[v][u]--;
        for (int j = 0; j < ve[i].size(); j++) {
          G[ve[i][j]].clear();
          for (map<int, int>::iterator it = mapa[ve[i][j]].begin();
               it != mapa[ve[i][j]].end(); it++) {
            if (it->second) G[ve[i][j]].push_back(it->first);
          }
        }
      } else
        ans.first += dp[i][1].first, ans.second += dp[i][1].second;
    }
  cout << ans.first << ' ' << ans.second << endl;
  for (int i = 1; i <= n; i++)
    if (father(i) == i) dfs3(i, 0, 1);
  return 0;
}
