#include <bits/stdc++.h>
const int INF = int(1e9);
const int N = 100000 + 10;
int n;
int f[N], s[N], c[N], state[N];
std::vector<int> adj[N];
inline std::pair<int, int> operator+(const std::pair<int, int>& a,
                                     const std::pair<int, int>& b) {
  return std::pair<int, int>(a.first + b.first, a.second + b.second);
}
std::pair<int, int> dp[N][2], max[N][2];
std::vector<std::pair<int, int> > record[N][2];
void solve(int x) {
  dp[x][0] = dp[x][1] = std::pair<int, int>(0, 0);
  record[x][0].push_back(dp[x][0]);
  record[x][1].push_back(dp[x][1]);
  for (int itr = 0; itr < ((int)(adj[x]).size()); itr++) {
    int y = adj[x][itr];
    solve(y);
    dp[x][1] =
        std::max(dp[x][0] + dp[y][0] + std::pair<int, int>(1, s[x] ^ s[y]),
                 dp[x][1] + std::max(dp[y][0], dp[y][1]));
    dp[x][0] = dp[x][0] + std::max(dp[y][0], dp[y][1]);
    record[x][0].push_back(dp[x][0]);
    record[x][1].push_back(dp[x][1]);
  }
}
void merge(int x, int t, std::vector<std::pair<int, int> >& project) {
  int k = ((int)(adj[x]).size()) - 1;
  for (int itr = ((int)(adj[x]).size()) - 1; itr >= 0; itr--) {
    int y = adj[x][itr];
    if (t == 0) {
      merge(y, dp[y][0] < dp[y][1], project);
    } else {
      if (record[x][0][k] + dp[y][0] + std::pair<int, int>(1, s[x] ^ s[y]) >
          record[x][1][k] + std::max(dp[y][0], dp[y][1])) {
        project.push_back(std::make_pair(x, y));
        merge(y, 0, project);
        t = 0;
      } else {
        merge(y, dp[y][0] < dp[y][1], project);
      }
    }
    k--;
  }
}
int main() {
  scanf("%d", &n);
  for (int i = 0; i < n; i++) {
    scanf("%d%d", f + i, s + i);
    f[i]--, s[i]--;
    c[f[i]]++;
  }
  std::vector<int> queue;
  for (int i = 0; i < n; i++) {
    if (c[i] == 0) {
      queue.push_back(i);
    }
  }
  for (int front = 0; front < ((int)(queue).size()); front++) {
    int x = queue[front];
    state[x] = 1;
    adj[f[x]].push_back(x);
    if (c[f[x]]-- == 1) {
      queue.push_back(f[x]);
    }
  }
  for (int i = 0; i < n; i++) {
    if (state[i] == 0) {
      solve(i);
    }
  }
  std::pair<int, int> result(0, 0);
  std::vector<std::pair<int, int> > project;
  for (int i = 0; i < n; i++) {
    if (state[i] == 0) {
      std::vector<int> list;
      for (int j = i; state[j] == 0; j = f[j]) {
        state[j] = 1;
        list.push_back(j);
      }
      max[0][0] = dp[list[0]][0];
      max[0][1] = dp[list[0]][1];
      for (int j = 1; j < ((int)(list).size()); j++) {
        max[j][0] = std::max(max[j - 1][0], max[j - 1][1]) + dp[list[j]][0];
        max[j][1] = max[j - 1][0] + dp[list[j]][0] +
                    std::pair<int, int>(1, s[list[j]] ^ s[list[j - 1]]);
        max[j][1] = std::max(
            max[j][1], std::max(max[j - 1][0], max[j - 1][1]) + dp[list[j]][1]);
      }
      std::pair<int, int> tmp = std::max(max[((int)(list).size()) - 1][0],
                                         max[((int)(list).size()) - 1][1]);
      max[0][0] = std::pair<int, int>(-INF, -INF);
      max[0][1] = dp[list[0]][0] +
                  std::pair<int, int>(1, s[list.front()] ^ s[list.back()]);
      for (int j = 1; j < ((int)(list).size()); j++) {
        max[j][0] = std::max(max[j - 1][0], max[j - 1][1]) + dp[list[j]][0];
        max[j][1] = max[j - 1][0] + dp[list[j]][0] +
                    std::pair<int, int>(1, s[list[j]] ^ s[list[j - 1]]);
        max[j][1] = std::max(
            max[j][1], std::max(max[j - 1][0], max[j - 1][1]) + dp[list[j]][1]);
      }
      if (max[((int)(list).size()) - 1][0] > tmp) {
        tmp = max[((int)(list).size()) - 1][0];
        for (int j = ((int)(list).size()) - 1, k = 0; j > 0; j--) {
          if (k == 0) {
            merge(list[j], 0, project);
            k = max[j - 1][0] < max[j - 1][1];
          } else {
            if (max[j - 1][0] + dp[list[j]][0] +
                    std::pair<int, int>(1, s[list[j]] ^ s[list[j - 1]]) >
                std::max(max[j - 1][0], max[j - 1][1]) + dp[list[j]][1]) {
              merge(list[j], 0, project);
              project.push_back(std::make_pair(list[j - 1], list[j]));
              k = 0;
            } else {
              merge(list[j], 1, project);
              k = max[j - 1][0] < max[j - 1][1];
            }
          }
        }
        project.push_back(std::make_pair(list.front(), list.back()));
        merge(list.front(), 0, project);
      } else {
        max[0][0] = dp[list[0]][0];
        max[0][1] = dp[list[0]][1];
        for (int j = 1; j < ((int)(list).size()); j++) {
          max[j][0] = std::max(max[j - 1][0], max[j - 1][1]) + dp[list[j]][0];
          max[j][1] = max[j - 1][0] + dp[list[j]][0] +
                      std::pair<int, int>(1, s[list[j]] ^ s[list[j - 1]]);
          max[j][1] =
              std::max(max[j][1],
                       std::max(max[j - 1][0], max[j - 1][1]) + dp[list[j]][1]);
        }
        int j = ((int)(list).size()) - 1;
        int k = max[j][0] < max[j][1];
        for (; j > 0; j--) {
          if (k == 0) {
            merge(list[j], 0, project);
            k = max[j - 1][0] < max[j - 1][1];
          } else {
            if (max[j - 1][0] + dp[list[j]][0] +
                    std::pair<int, int>(1, s[list[j]] ^ s[list[j - 1]]) >
                std::max(max[j - 1][0], max[j - 1][1]) + dp[list[j]][1]) {
              merge(list[j], 0, project);
              project.push_back(std::make_pair(list[j - 1], list[j]));
              k = 0;
            } else {
              merge(list[j], 1, project);
              k = max[j - 1][0] < max[j - 1][1];
            }
          }
        }
        merge(list[j], k, project);
      }
      result = result + tmp;
    }
  }
  printf("%d %d\n", result.first, result.second);
  for (int i = 0; i < ((int)(project).size()); i++) {
    printf("%d %d\n", project[i].first + 1, project[i].second + 1);
  }
}
