#include <bits/stdc++.h>
using namespace std;
const int maxn = 100010;
int in[maxn], cnt, en, t, low[maxn], dfn[maxn], n, sex[maxn], belong[maxn],
    ans1, ans2, to[maxn], to2[maxn][2][2];
bool tag[maxn], instack[maxn];
stack<int> sta;
vector<int> p[maxn];
vector<pair<int, int> > ans;
struct rec {
  int sum, bg;
  rec() { sum = bg = 0; }
  rec(int a, int b) {
    sum = a;
    bg = b;
  }
  bool operator<(const rec &a) const {
    if (sum != a.sum)
      return sum < a.sum;
    else
      return bg < a.bg;
  }
  rec operator+(const rec &a) const { return rec(sum + a.sum, bg + a.bg); }
  rec operator-(const rec &a) const { return rec(sum - a.sum, bg - a.bg); }
} f[maxn][2], g[maxn][2][2];
struct edge {
  int e;
  edge *next;
} * v[maxn], ed[maxn];
void add_edge(int s, int e) {
  en++;
  ed[en].next = v[s];
  v[s] = ed + en;
  v[s]->e = e;
}
void dfs(int now) {
  t++;
  dfn[now] = low[now] = t;
  instack[now] = true;
  sta.push(now);
  for (edge *e = v[now]; e; e = e->next)
    if (!dfn[e->e]) {
      dfs(e->e);
      low[now] = min(low[e->e], low[now]);
    } else {
      if (instack[e->e]) low[now] = min(low[now], dfn[e->e]);
    }
  if (low[now] == dfn[now]) {
    cnt++;
    while (sta.top() != now) {
      belong[sta.top()] = cnt;
      p[cnt].push_back(sta.top());
      instack[sta.top()] = false;
      sta.pop();
    }
    p[cnt].push_back(now);
    belong[now] = cnt;
    instack[now] = false;
    sta.pop();
  }
}
void dfs2(int now) {
  for (edge *e = v[now]; e; e = e->next)
    if (!tag[e->e]) {
      dfs2(e->e);
      f[now][0] = f[now][0] + max(f[e->e][0], f[e->e][1]);
    }
  for (edge *e = v[now]; e; e = e->next)
    if (!tag[e->e]) {
      rec nowv = f[now][0] - max(f[e->e][0], f[e->e][1]) + f[e->e][0];
      nowv.sum++;
      if (sex[now] != sex[e->e]) nowv.bg++;
      if (f[now][1] < nowv) {
        to[now] = e->e;
        f[now][1] = nowv;
      }
    }
}
void dfs3(int now, int cur) {
  if (cur == -1) {
    if (f[now][0] < f[now][1]) {
      ans.push_back(make_pair(now, to[now]));
      for (edge *e = v[now]; e; e = e->next)
        if (!tag[e->e]) {
          if (e->e == to[now])
            dfs3(e->e, 0);
          else
            dfs3(e->e, -1);
        }
    } else {
      for (edge *e = v[now]; e; e = e->next)
        if (!tag[e->e]) dfs3(e->e, -1);
    }
  } else {
    if (cur == 0) {
      for (edge *e = v[now]; e; e = e->next)
        if (!tag[e->e]) dfs3(e->e, -1);
    } else {
      ans.push_back(make_pair(now, to[now]));
      for (edge *e = v[now]; e; e = e->next)
        if (!tag[e->e]) {
          if (e->e == to[now])
            dfs3(e->e, 0);
          else
            dfs3(e->e, -1);
        }
    }
  }
}
int main() {
  scanf("%d", &n);
  for (int a = 1; a <= n; a++) {
    int s;
    scanf("%d%d", &s, &sex[a]);
    add_edge(s, a);
  }
  for (int a = 1; a <= n; a++)
    if (!dfn[a]) dfs(a);
  for (int a = 1; a <= n; a++)
    for (edge *e = v[a]; e; e = e->next)
      if (belong[a] != belong[e->e]) in[belong[e->e]]++;
  for (int a = 1; a <= cnt; a++)
    if (!in[a]) {
      if ((int)p[a].size() == 1) continue;
      for (int b = 0; b < (int)p[a].size(); b++) tag[p[a][b]] = true;
      for (int b = 0; b < (int)p[a].size(); b++) dfs2(p[a][b]);
      g[0][0][0] = f[p[a][0]][0];
      g[0][1][1] = f[p[a][0]][1];
      for (int b = 1; b < (int)p[a].size(); b++)
        for (int c = 1; c >= 0; c--) {
          int cnt = 0;
          for (edge *e = v[p[a][b]]; e; e = e->next)
            if (!tag[e->e]) cnt++;
          g[b][0][c] = g[b][1][c] = rec(0, 0);
          if (b == 1) {
            g[b][0][c] = g[b - 1][c][c] + f[p[a][b]][0];
            to2[b][0][c] = to2[b][1][c] = c;
            if (cnt)
              g[b][1][c] = g[b - 1][c][c] + max(f[p[a][b]][1], f[p[a][b]][0]);
            if (c == 0) {
              rec nowv = g[b - 1][c][c] + f[p[a][b]][0];
              nowv.sum++;
              if (sex[p[a][b]] != sex[p[a][b - 1]]) nowv.bg++;
              if (g[b][1][1] < nowv) {
                g[b][1][1] = nowv;
                to2[b][1][1] = 2;
              }
            }
            continue;
          }
          g[b][0][c] = g[b][1][c] = rec(0, 0);
          if (g[b - 1][0][c] < g[b - 1][1][c])
            to2[b][0][c] = to2[b][1][c] = 1;
          else
            to2[b][0][c] = to2[b][1][c] = 0;
          g[b][0][c] = max(g[b - 1][0][c], g[b - 1][1][c]) + f[p[a][b]][0];
          if (cnt)
            g[b][1][c] = max(g[b - 1][0][c], g[b - 1][1][c]) + f[p[a][b]][1];
          rec nowv = g[b - 1][0][c] + f[p[a][b]][0];
          nowv.sum++;
          if (sex[p[a][b - 1]] != sex[p[a][b]]) nowv.bg++;
          if (g[b][1][c] < nowv) to2[b][1][c] = 2;
          g[b][1][c] = max(g[b][1][c], nowv);
        }
      int nowp = 0, sa, sb, sc;
      if (g[p[a].size() - 1][1][1] <
          max(g[p[a].size() - 1][1][0], g[p[a].size() - 1][0][1])) {
        if (g[p[a].size() - 1][1][0] < g[p[a].size() - 1][0][1])
          nowp = 3;
        else
          nowp = 2;
      } else
        nowp = 1;
      rec nowans = max(g[p[a].size() - 1][1][1],
                       max(g[p[a].size() - 1][1][0], g[p[a].size() - 1][0][1]));
      if ((int)p[a].size() != 1) {
        rec nowv = g[p[a].size() - 1][0][0];
        nowv.sum++;
        if (sex[p[a][0]] != sex[p[a][p[a].size() - 1]]) nowv.bg++;
        if (nowans < nowv) {
          nowp = 0;
          sb = 0;
          sc = 0;
          ans.push_back(make_pair(p[a][p[a].size() - 1], p[a][0]));
        }
        nowans = max(nowans, nowv);
      }
      if (nowp) {
        if (nowp == 1)
          sb = 1, sc = 1;
        else {
          if (nowp == 2)
            sb = 1, sc = 0;
          else
            sb = 0, sc = 1;
        }
      }
      for (sa = p[a].size() - 1; sa >= 0 && g[sa][sb][sc].sum > 0; sa--) {
        if (sb == 0) {
          dfs3(p[a][sa], 0);
          sb = to2[sa][sb][sc];
        } else {
          if (sb == 1) {
            if (to2[sa][sb][sc] != 2) {
              dfs3(p[a][sa], 1);
              sb = to2[sa][sb][sc];
            } else {
              dfs3(p[a][sa], 0);
              ans.push_back(make_pair(p[a][sa], p[a][sa - 1]));
              sb = 0;
            }
          }
        }
      }
      if (sa == 0) {
        if (sb == 0 && sc == 1) dfs3(p[a][0], 0);
      }
      ans1 += nowans.sum;
      ans2 += nowans.bg;
    }
  printf("%d %d\n", ans1, ans2);
  for (int a = 0; a < ans1; a++) printf("%d %d\n", ans[a].first, ans[a].second);
  return 0;
}
