#include <bits/stdc++.h>
using namespace std;

ifstream in("pairs.in");
ofstream out("pairs.out");

const int DIM = 1e5 + 5;

int nxt[DIM], val[DIM], pos[DIM];

pair<int, int> tdp[DIM][2], cdp[DIM], arr[2][DIM]; deque<int> chn;
bitset<DIM> oki, mrk, ist; vector<pair<int, int>> sol; vector<int> edg[DIM];

pair<int, int> operator + (const pair<int, int> &p1, const pair<int, int> &p2) {
    return pair<int, int>(p1.first + p2.first, p1.second + p2.second);
}

pair<int, int> operator - (const pair<int, int> &p1, const pair<int, int> &p2) {
    return pair<int, int>(p1.first - p2.first, p1.second - p2.second);
}

void calcdp(int x)
{
    mrk[x] = true;
    tdp[x][0] = tdp[x][1] = pair<int, int>(0, 0);

    vector<int> aux;
    for (int y : edg[x])
        calcdp(y), aux.push_back(y);

    for (int y : aux)
        tdp[x][0] = tdp[x][0] + max(tdp[y][0], tdp[y][1]);

    for (int y : aux) {
        pair<int, int> aux = tdp[x][0] - max(tdp[y][0], tdp[y][1]) +
                  tdp[y][0] + pair<int, int>(1, val[x] != val[y]);

        if (tdp[x][1] < aux)
            tdp[x][1] = aux, pos[x] = y;
    }
}

int _nr[2];
void solvedp(int x, bool ok, int nr)
{
    vector<int> aux;
    for (int y : edg[x])
        calcdp(y), aux.push_back(y);

    if (ok and tdp[x][0] >= tdp[x][1])
        ok = false;

    if (!ok) {
        for (int y : aux)
            solvedp(y, true, nr);
    } else {
        arr[nr][++_nr[nr]] = make_pair(x, pos[x]);
        for (int y : aux)
            solvedp(y, y != pos[x], nr);
    }
}

int main(void)
{
    int n; scanf("%d", &n);
    for (int i = 1; i <= n; ++i) {
        scanf("%d %d", &nxt[i], &val[i]);
        edg[nxt[i]].push_back(i);
    }

    pair<int, int> ans;
    for (int i = 1; i <= n; ++i) if (!mrk[i]) {
        chn.clear();
        for (int x = i; true; x = nxt[x]) {
            chn.push_back(x);

            if (!oki[x])
                oki[x] = true;
            else {
                while (chn.front() != chn.back())
                    oki[chn.front()] = false, chn.pop_front();
                break;
            }
        }

        pair<int, int> pr1, pr2;

        edg[chn[1]].erase(find(edg[chn[1]].begin(), edg[chn[1]].end(), chn[0]));
        calcdp(chn[0]); _nr[0] = 0; solvedp(chn[0], true, 0); edg[chn[1]].push_back(chn[0]);
        pr1 = max(tdp[chn[0]][0], tdp[chn[0]][1]);

        edg[chn[2]].erase(find(edg[chn[2]].begin(), edg[chn[2]].end(), chn[1]));
        calcdp(chn[1]); _nr[1] = 0; solvedp(chn[1], true, 1); edg[chn[2]].push_back(chn[1]);
        pr2 = max(tdp[chn[1]][0], tdp[chn[1]][1]);

        if (pr1 > pr2) {
            ans = ans + pr1;
            for (int i = 1; i <= pr1.first; ++i)
                sol.push_back(arr[0][i]);
        } else {
            ans = ans + pr2;
            for (int i = 1; i <= pr2.first; ++i)
                sol.push_back(arr[1][i]);
        }
    }

    printf("%d %d\n", ans.first, ans.second);
    for (pair<int, int> pr : sol)
        printf("%d %d\n", pr.first, pr.second);

    return 0;
}


#include <bits/stdc++.h>
using namespace std;

ifstream in("pairs.in");
ofstream out("pairs.out");

const long long DIM = 1e5 + 5;

struct str
{
    long long x, y;
    str(long long _x = 0, long long _y = 0) {
        x = _x;
        y = _y;
    }

    inline str operator +(const str &a) const {
        return str(x + a.x, y + a.y);
    }

    inline str operator -(const str &a) const {
        return str(x - a.x, y - a.y);
    }

    inline str operator +=(const str &a) {
        return *this = *this + a;
    }

    inline bool operator <(const str &a) const {
        if (x == a.x)
            return y < a.y;
        return x < a.x;
    }

    inline bool operator >(const str &a) const {
        if (x == a.x)
            return y > a.y;
        return x > a.x;
    }

    inline bool operator <=(const str &a) const {
        if (x == a.x)
            return y <= a.y;
        return x < a.x;
    }

    inline bool operator >=(const str &a) const {
        if (x == a.x)
            return y >= a.y;
        return x > a.x;
    }

    inline bool operator ==(const str &a) const {
        if (x == a.x)
            return y == a.y;
        return x == a.x;
    }
} tdp[DIM][2], cdp[DIM];

long long nxt[DIM], val[DIM], pos[DIM];

bitset<DIM> oki, mrk, ist;
vector<long long> edg[DIM]; deque<long long> chn;
vector<pair<long long, long long>> sol, aux1, aux2;

str calccst(vector<pair<long long, long long>> &arr)
{
    long long cst = 0;
    for (pair<long long, long long> pr : arr)
        cst += val[pr.first] != val[pr.second];

    return str((long long) arr.size(), cst);
}

void calcdp(long long x)
{
    vector<long long> aux; mrk[x] = true;
    for (long long y : edg[x]) if (!oki[y])
        calcdp(y), aux.push_back(y);

    for (long long y : aux)
        tdp[x][0] += max(tdp[y][0], tdp[y][1]);

    for (long long y : aux) {
        str aux = tdp[x][0] - max(tdp[y][0], tdp[y][1]) +
        tdp[y][0] + str(1, val[x] != val[y]);

        if (tdp[x][1] < aux)
            tdp[x][1] = aux, pos[x] = y;
    }
}

void solvedp(long long x, bool ok, vector<pair<long long, long long>> &arr)
{
    vector<long long> aux;
    for (long long y : edg[x]) if (!oki[y])
        calcdp(y), aux.push_back(y);

    if (ok and tdp[x][0] >= tdp[x][1])
        ok = false;

    if (!ok) {
        for (long long y : aux)
            solvedp(y, true, arr);
    } else {
        arr.push_back(make_pair(x, pos[x]));
        for (long long y : aux)
            solvedp(y, y != pos[x], arr);
    }
}

void calccdp(long long le, long long ri, deque<long long> &chn, vector<pair<long long, long long>> &arr)
{
    for (long long i = le; i <= ri; ++i) {
        if (i == le)
            cdp[i] = max(tdp[chn[i]][0], tdp[chn[i]][1]);
        else
        if (i == le + 1)
            cdp[i] = max(max(tdp[chn[i]][0], tdp[chn[i]][1]) + cdp[i - 1],
                         tdp[chn[i - 1]][0] + tdp[chn[i]][0] + str(1, val[chn[i - 1]] != val[chn[i]]));
        else
            cdp[i] = max(max(tdp[chn[i]][0], tdp[chn[i]][1]) + cdp[i - 1],
                         tdp[chn[i - 1]][0] + tdp[chn[i]][0] + str(1, val[chn[i - 1]] != val[chn[i]]) + cdp[i - 2]);
    }

    for (long long i = ri; i >= le; ) {
        if (i == le or cdp[i] == max(tdp[chn[i]][0], tdp[chn[i]][1]) + cdp[i - 1])
            solvedp(chn[i], true, arr), i -= 1;
        else {
            solvedp(chn[i - 1], false, arr); solvedp(chn[i], false, arr);
            arr.push_back(make_pair(chn[i - 1], chn[i])); i -= 2;
        }
    }
}

int main(void)
{
    long long n; cin >> n;
    for (long long i = 1; i <= n; ++i) {
        cin >> nxt[i] >> val[i];
        edg[nxt[i]].push_back(i);
    }

    for (long long i = 1; i <= n; ++i) if (!mrk[i]) {
        chn.clear();
        for (long long x = i; true; x = nxt[x]) {
            chn.push_back(x);

            if (!oki[x])
                oki[x] = true;
            else {
                while (chn.front() != chn.back())
                    oki[chn.front()] = false, chn.pop_front();
                break;
            }
        }

        for (long long i = 1; i < chn.size(); ++i)
            calcdp(chn[i]);

        aux1.clear(); aux2.clear();
        calccdp(0, (long long) chn.size() - 2, chn, aux1),
        calccdp(1, (long long) chn.size() - 1, chn, aux2);

        if (calccst(aux1) < calccst(aux2))
            swap(aux1, aux2);
        for (pair<long long, long long> pr : aux1)
            sol.push_back(pr);
    }

    cout << sol.size() << " " << calccst(sol).y << "\n";
    for (pair<long long, long long> pr : sol)
        cout << pr.first << " " << pr.second << "\n";

    return 0;
}


#include <bits/stdc++.h>
using namespace std;

ifstream in("pairs.in");
ofstream out("pairs.out");

const int DIM = 1e5 + 5;
const int INF = 1e9 + 7;

int val[DIM], fth[DIM], lev[DIM], pos[DIM];

vector<int> edg[DIM], stk, aux, lst;
bitset<DIM> oki, mrk; vector<pair<int, int>> sol;

struct str
{
    int x, y;
    str(int _x = 0, int _y = 0) {
        x = _x;
        y = _y;
    }

    inline str operator +(const str &a) const {
        return str(x + a.x, y + a.y);
    }

    inline str operator -(const str &a) const {
        return str(x - a.x, y - a.y);
    }

    inline str operator +=(const str &a) {
        return *this = *this + a;
    }

    inline bool operator <(const str &a) const {
        if (x == a.x)
            return y < a.y;
        return x < a.x;
    }

    inline bool operator >(const str &a) const {
        if (x == a.x)
            return y > a.y;
        return x > a.x;
    }

    inline bool operator <=(const str &a) const {
        if (x == a.x)
            return y <= a.y;
        return x < a.x;
    }

    inline bool operator >=(const str &a) const {
        if (x == a.x)
            return y >= a.y;
        return x > a.x;
    }
} dp[DIM][2];

void dfs(int x, int f, pair<int, int> &ed)
{
    stk.push_back(x); fth[x] = f; bool ok = false;
    oki[x] = mrk[x] = true; lev[x] = lev[f] + 1;

    for (int y : edg[x]) {
        if (y == f) {
            if (ok)
                ed = make_pair(x, y);
            ok = true; continue;
        }

        if (!oki[y])
            dfs(y, x, ed);
        else
        if (lev[y] < lev[x]) {
            for (int z = x; z != fth[y]; z = fth[z])
                aux.push_back(z);
            ed = make_pair(x, y);
        }
    }

    stk.pop_back();
}

void calcdp(int x, int f, pair<int, int> ed, bool ok)
{
    if (ok)
        mrk[x] = false;

    vector<int> aux; vector<str> dpl, dpr;
    dp[x][0] = str(0, 0); dp[x][1] = str(-INF, -INF);

    for (int y : edg[x]) {
        if (y == f or (x == ed.first and y == ed.second)
                   or (y == ed.first and x == ed.second))
            continue;
        calcdp(y, x, ed, ok); aux.push_back(y);
    }

    for (int y : aux)
        dp[x][0] += max(dp[y][0], dp[y][1]);

    dpl.resize(aux.size());
    for (int i = 0; i < aux.size(); ++i) {
        dpl[i] = max(dp[aux[i]][0], dp[aux[i]][1]);

        if (i - 1 >= 0)
            dpl[i] += dpl[i - 1];
    }

    dpr.resize(aux.size());
    for (int i = (int) aux.size() - 1; i >= 0; --i) {
        dpr[i] = max(dp[aux[i]][0], dp[aux[i]][1]);

        if (i + 1 < aux.size())
            dpr[i] += dpr[i + 1];
    }

    for (int i = 0; i < aux.size(); ++i) {
        str cns = str(1, val[x] != val[aux[i]]) + dp[aux[i]][0];

        if (i - 1 >= 0) cns += dpl[i - 1];
        if (i + 1 < aux.size()) cns += dpr[i + 1];

        if (dp[x][1] < cns)
            dp[x][1] = cns, pos[x] = aux[i];
    }
}

// 0 - blocked, 1 - must take, 2 - 0 or 1
void solvedp(int x, int f, pair<int, int> ed, int msk)
{
    vector<int> aux;
    for (int y : edg[x]) {
        if (y == f or (x == ed.first and y == ed.second)
                   or (y == ed.first and x == ed.second))
            continue;

        aux.push_back(y);
    }

    if (!msk or (msk == 2 and dp[x][0] >= dp[x][1])) {
        for (int y : aux)
            solvedp(y, x, ed, 2);
    } else {
        sol.push_back(make_pair(x, pos[x]));
        for (int y : aux) if (y != pos[x])
            solvedp(y, x, ed, 2);
        solvedp(pos[x], x, ed, 0);
    }
}

int main(void)
{
    int n;
    cin >> n;

    for (int i = 1; i <= n; ++i) {
        int x;
        cin >> x >> val[i];

        edg[i].push_back(x);
        edg[x].push_back(i);
    }

    str ans;
    for (int i = 1; i <= n; ++i) {
        if (oki[i])
            continue;
        pair<int, int> ed;
        aux.clear(); lst.clear(); dfs(i, 0, ed);

        calcdp(ed.first, 0, ed, false);
        str vl1 = max(dp[ed.first][0], dp[ed.first][1]),
            vl2 = str(1, val[ed.first] != val[ed.second]);

        for (int x : edg[ed.first])
            edg[x].erase(find(edg[x].begin(), edg[x].end(), ed.first));
        for (int x : edg[ed.second])
            edg[x].erase(find(edg[x].begin(), edg[x].end(), ed.second));

        for (int x : edg[ed.first]) {
            if (!mrk[x] or x == ed.second)
                continue;
            lst.push_back(x); calcdp(x, 0, ed, true);
            vl2 += max(dp[x][0], dp[x][1]);
        }

        for (int x : edg[ed.second]) {
            if (!mrk[x] or x == ed.first)
                continue;
            lst.push_back(x); calcdp(x, 0, ed, true);
            vl2 += max(dp[x][0], dp[x][1]);
        }

        for (int x : edg[ed.first])
            edg[x].push_back(ed.first);
        for (int x : edg[ed.second])
            edg[x].push_back(ed.second);

        if (vl1 > vl2) {
            ans += vl1;
            solvedp(ed.first, 0, ed, 2);
        } else {
            ans += vl2;
            for (int x : edg[ed.first])
                edg[x].erase(find(edg[x].begin(), edg[x].end(), ed.first));
            for (int x : edg[ed.second])
                edg[x].erase(find(edg[x].begin(), edg[x].end(), ed.second));

            for (int x : lst)
                solvedp(x, 0, ed, 2);
            sol.push_back(ed);
        }
    }

    cout << ans.x << " " << ans.y << "\n";
    for (pair<int, int> pr : sol)
        cout << pr.first << " " << pr.second << "\n";

    return 0;
}


#include <bits/stdc++.h>
using namespace std;

ifstream in("pairs.in");
ofstream out("pairs.out");

const int DIM = 1e5 + 5;

int nxt[DIM], val[DIM], pos[DIM];

pair<int, int> tdp[DIM][2], cdp[DIM], arr[2][DIM]; deque<int> chn;
bitset<DIM> oki, mrk, ist; vector<pair<int, int>> sol; vector<int> edg[DIM];

pair<int, int> operator + (const pair<int, int> &p1, const pair<int, int> &p2) {
    return pair<int, int>(p1.first + p2.first, p1.second + p2.second);
}

pair<int, int> operator - (const pair<int, int> &p1, const pair<int, int> &p2) {
    return pair<int, int>(p1.first - p2.first, p1.second - p2.second);
}

void calcdp(int x)
{
    mrk[x] = true;
    tdp[x][0] = tdp[x][1] = pair<int, int>(0, 0);

    for (int y : edg[x]) {
        calcdp(y);
        tdp[x][0] = tdp[x][0] + max(tdp[y][0], tdp[y][1]);

        pair<int, int> aux = tdp[y][0] - max(tdp[y][0], tdp[y][1]) +
                             pair<int, int>(1, val[x] != val[y]);
        if (tdp[x][1] < aux)
            tdp[x][1] = aux, pos[x] = y;
    }

    tdp[x][1] = tdp[x][1] + tdp[x][0];
}

int _nr[2];
void solvedp(int x, bool ok, int nr)
{
    if (ok and tdp[x][0] >= tdp[x][1])
        ok = false;
    if (ok)
        arr[nr][++_nr[nr]] = make_pair(x, pos[x]);
    for (int y : edg[x])
        solvedp(y, y != pos[x], nr);
}

int main(void)
{
    int n; scanf("%d", &n);
    for (int i = 1; i <= n; ++i) {
        scanf("%d %d", &nxt[i], &val[i]);
        edg[nxt[i]].push_back(i);
    }

    pair<int, int> ans;
    for (int i = 1; i <= n; ++i) if (!mrk[i]) {
        chn.clear();
        for (int x = i; true; x = nxt[x]) {
            chn.push_back(x);

            if (!oki[x])
                oki[x] = true;
            else {
                while (chn.front() != chn.back())
                    oki[chn.front()] = false, chn.pop_front();
                break;
            }
        }

        pair<int, int> pr1, pr2;

        edg[chn[1]].erase(find(edg[chn[1]].begin(), edg[chn[1]].end(), chn[0]));
        calcdp(chn[0]); _nr[0] = 0; solvedp(chn[0], true, 0); edg[chn[1]].push_back(chn[0]);
        pr1 = max(tdp[chn[0]][0], tdp[chn[0]][1]);

        edg[chn[2]].erase(find(edg[chn[2]].begin(), edg[chn[2]].end(), chn[1]));
        calcdp(chn[1]); _nr[1] = 0; solvedp(chn[1], true, 1); edg[chn[2]].push_back(chn[1]);
        pr2 = max(tdp[chn[1]][0], tdp[chn[1]][1]);

        if (pr1 > pr2) {
            ans = ans + pr1;
            for (int i = 1; i <= pr1.first; ++i)
                sol.push_back(arr[0][i]);
        } else {
            ans = ans + pr2;
            for (int i = 1; i <= pr2.first; ++i)
                sol.push_back(arr[1][i]);
        }
    }

    printf("%d %d\n", ans.first, ans.second);
    for (pair<int, int> pr : sol)
        printf("%d %d\n", pr.first, pr.second);

    return 0;
}


#include <bits/stdc++.h>
using namespace std;

ifstream in("pairs.in");
ofstream out("pairs.out");

const int DIM = 1e5 + 5;
const int INF = 1e9 + 7;

int val[DIM], fth[DIM], lev[DIM], pos[DIM];

vector<int> edg[DIM], stk, aux, lst;
bitset<DIM> oki, mrk; vector<pair<int, int>> sol;

struct str
{
    int x, y;
    str(int _x = 0, int _y = 0) {
        x = _x;
        y = _y;
    }

    inline str operator +(const str &a) const {
        return str(x + a.x, y + a.y);
    }

    inline str operator -(const str &a) const {
        return str(x - a.x, y - a.y);
    }

    inline str operator +=(const str &a) {
        return *this = *this + a;
    }

    inline bool operator <(const str &a) const {
        if (x == a.x)
            return y < a.y;
        return x < a.x;
    }

    inline bool operator >(const str &a) const {
        if (x == a.x)
            return y > a.y;
        return x > a.x;
    }

    inline bool operator <=(const str &a) const {
        if (x == a.x)
            return y <= a.y;
        return x < a.x;
    }

    inline bool operator >=(const str &a) const {
        if (x == a.x)
            return y >= a.y;
        return x > a.x;
    }
} dp[DIM][2];

void dfs(int x, int f, pair<int, int> &ed)
{
    stk.push_back(x); fth[x] = f; bool ok = false;
    oki[x] = mrk[x] = true; lev[x] = lev[f] + 1;

    for (int y : edg[x]) {
        if (y == f) {
            if (ok)
                ed = make_pair(x, y);
            ok = true; continue;
        }

        if (!oki[y])
            dfs(y, x, ed);
        else
        if (lev[y] < lev[x]) {
            for (int z = x; z != fth[y]; z = fth[z])
                aux.push_back(z);
            ed = make_pair(x, y);
        }
    }

    stk.pop_back();
}

void calcdp(int x, int f, pair<int, int> ed, bool ok)
{
    if (ok)
        mrk[x] = false;

    vector<int> aux; vector<str> dpl, dpr;
    dp[x][0] = str(0, 0); dp[x][1] = str(-INF, -INF);

    for (int y : edg[x]) {
        if (y == f or (x == ed.first and y == ed.second)
                   or (y == ed.first and x == ed.second))
            continue;
        calcdp(y, x, ed, ok); aux.push_back(y);
    }

    for (int y : aux)
        dp[x][0] += max(dp[y][0], dp[y][1]);

    dpl.resize(aux.size());
    for (int i = 0; i < aux.size(); ++i) {
        dpl[i] = max(dp[aux[i]][0], dp[aux[i]][1]);

        if (i - 1 >= 0)
            dpl[i] += dpl[i - 1];
    }

    dpr.resize(aux.size());
    for (int i = (int) aux.size() - 1; i >= 0; --i) {
        dpr[i] = max(dp[aux[i]][0], dp[aux[i]][1]);

        if (i + 1 < aux.size())
            dpr[i] += dpr[i + 1];
    }

    for (int i = 0; i < aux.size(); ++i) {
        str cns = str(1, val[x] != val[aux[i]]) + dp[aux[i]][0];

        if (i - 1 >= 0) cns += dpl[i - 1];
        if (i + 1 < aux.size()) cns += dpr[i + 1];

        if (dp[x][1] < cns)
            dp[x][1] = cns, pos[x] = aux[i];
    }
}

// 0 - blocked, 1 - must take, 2 - 0 or 1
void solvedp(int x, int f, pair<int, int> ed, int msk)
{
    vector<int> aux;
    for (int y : edg[x]) {
        if (y == f or (x == ed.first and y == ed.second)
                   or (y == ed.first and x == ed.second))
            continue;

        aux.push_back(y);
    }

    if (!msk or (msk == 2 and dp[x][0] >= dp[x][1])) {
        for (int y : aux)
            solvedp(y, x, ed, 2);
    } else {
        sol.push_back(make_pair(x, pos[x]));
        for (int y : aux) if (y != pos[x])
            solvedp(y, x, ed, 2);
        solvedp(pos[x], x, ed, 0);
    }
}

int main(void)
{
    int n;
    cin >> n;

    for (int i = 1; i <= n; ++i) {
        int x;
        cin >> x >> val[i];

        edg[i].push_back(x);
        edg[x].push_back(i);
    }

    str ans;
    for (int i = 1; i <= n; ++i) {
        if (oki[i])
            continue;
        pair<int, int> ed;
        aux.clear(); lst.clear(); dfs(i, 0, ed);

        if (count(edg[ed.first].begin(), edg[ed.first].end(), ed.second) > 1)
            edg[ed.first].erase(find(edg[ed.first].begin(), edg[ed.first].end(), ed.second));
        if (count(edg[ed.second].begin(), edg[ed.second].end(), ed.first) > 1)
            edg[ed.second].erase(find(edg[ed.second].begin(), edg[ed.second].end(), ed.first));

        calcdp(ed.first, 0, ed, false);
        str vl1 = max(dp[ed.first][0], dp[ed.first][1]),
            vl2 = str(1, val[ed.first] != val[ed.second]);

        for (int x : edg[ed.first])
            edg[x].erase(find(edg[x].begin(), edg[x].end(), ed.first));
        for (int x : edg[ed.second])
            edg[x].erase(find(edg[x].begin(), edg[x].end(), ed.second));

        for (int x : edg[ed.first]) {
            if (!mrk[x] or x == ed.second)
                continue;
            lst.push_back(x); calcdp(x, 0, ed, true);
            vl2 += max(dp[x][0], dp[x][1]);
        }

        for (int x : edg[ed.second]) {
            if (!mrk[x] or x == ed.first)
                continue;
            lst.push_back(x); calcdp(x, 0, ed, true);
            vl2 += max(dp[x][0], dp[x][1]);
        }

        if (vl1 > vl2) {
            ans += vl1;
            for (int x : edg[ed.first])
                edg[x].push_back(ed.first);
            for (int x : edg[ed.second])
                edg[x].push_back(ed.second);
            solvedp(ed.first, 0, ed, 2);
        } else {
            ans += vl2;
            for (int x : lst)
                solvedp(x, 0, ed, 2);
            sol.push_back(ed);
        }
    }

    cout << ans.x << " " << ans.y << "\n";
    for (pair<int, int> pr : sol)
        cout << pr.first << " " << pr.second << "\n";

    return 0;
}


#include <bits/stdc++.h>
using namespace std;

ifstream in("pairs.in");
ofstream out("pairs.out");

const int DIM = 1e5 + 5;
const int INF = 1e9 + 7;

int val[DIM], fth[DIM], lev[DIM], pos[DIM];

vector<int> edg[DIM], stk, aux, lst;
bitset<DIM> oki, mrk; vector<pair<int, int>> sol;

struct str
{
    int x, y;
    str(int _x = 0, int _y = 0) {
        x = _x;
        y = _y;
    }

    inline str operator +(const str &a) const {
        return str(x + a.x, y + a.y);
    }

    inline str operator -(const str &a) const {
        return str(x - a.x, y - a.y);
    }

    inline str operator +=(const str &a) {
        return *this = *this + a;
    }

    inline bool operator <(const str &a) const {
        if (x == a.x)
            return y < a.y;
        return x < a.x;
    }

    inline bool operator >(const str &a) const {
        if (x == a.x)
            return y > a.y;
        return x > a.x;
    }

    inline bool operator <=(const str &a) const {
        if (x == a.x)
            return y <= a.y;
        return x < a.x;
    }

    inline bool operator >=(const str &a) const {
        if (x == a.x)
            return y >= a.y;
        return x > a.x;
    }
} dp[DIM][2];

void dfs(int x, int f, pair<int, int> &ed)
{
    stk.push_back(x); fth[x] = f; bool ok = false;
    oki[x] = mrk[x] = true; lev[x] = lev[f] + 1;

    for (int y : edg[x]) {
        if (y == f) {
            if (ok)
                ed = make_pair(x, y);
            ok = true; continue;
        }

        if (!oki[y])
            dfs(y, x, ed);
        else
        if (lev[y] < lev[x]) {
            for (int z = x; z != fth[y]; z = fth[z])
                aux.push_back(z);
            ed = make_pair(x, y);
        }
    }

    stk.pop_back();
}

void calcdp(int x, int f, pair<int, int> ed, bool ok)
{
    if (ok)
        mrk[x] = false;

    vector<int> aux; vector<str> dpl, dpr;
    dp[x][0] = str(0, 0); dp[x][1] = str(-INF, -INF);

    for (int y : edg[x]) {
        if (y == f or (x == ed.first and y == ed.second)
                   or (y == ed.first and x == ed.second))
            continue;
        calcdp(y, x, ed, ok); aux.push_back(y);
    }

    for (int y : aux)
        dp[x][0] += max(dp[y][0], dp[y][1]);

    dpl.resize(aux.size());
    for (int i = 0; i < aux.size(); ++i) {
        dpl[i] = max(dp[aux[i]][0], dp[aux[i]][1]);

        if (i - 1 >= 0)
            dpl[i] += dpl[i - 1];
    }

    dpr.resize(aux.size());
    for (int i = (int) aux.size() - 1; i >= 0; --i) {
        dpr[i] = max(dp[aux[i]][0], dp[aux[i]][1]);

        if (i + 1 < aux.size())
            dpr[i] += dpr[i + 1];
    }

    for (int i = 0; i < aux.size(); ++i) {
        str cns = str(1, val[x] != val[aux[i]]) + dp[aux[i]][0];

        if (i - 1 >= 0) cns += dpl[i - 1];
        if (i + 1 < aux.size()) cns += dpr[i + 1];

        if (dp[x][1] < cns)
            dp[x][1] = cns, pos[x] = aux[i];
    }
}

// 0 - blocked, 1 - must take, 2 - 0 or 1
void solvedp(int x, int f, pair<int, int> ed, int msk)
{
    vector<int> aux;
    for (int y : edg[x]) {
        if (y == f or (x == ed.first and y == ed.second)
                   or (y == ed.first and x == ed.second))
            continue;

        aux.push_back(y);
    }

    if (!msk or (msk == 2 and dp[x][0] >= dp[x][1])) {
        for (int y : aux)
            solvedp(y, x, ed, 2);
    } else {
        sol.push_back(make_pair(x, pos[x]));
        for (int y : aux) if (y != pos[x])
            solvedp(y, x, ed, 2);
        solvedp(pos[x], x, ed, 0);
    }
}

int main(void)
{
    int n;
    cin >> n;

    for (int i = 1; i <= n; ++i) {
        int x;
        cin >> x >> val[i];

        edg[i].push_back(x);
        edg[x].push_back(i);
    }

    str ans;
    for (int i = 1; i <= n; ++i) {
        if (oki[i])
            continue;
        pair<int, int> ed;
        aux.clear(); lst.clear(); dfs(i, 0, ed);

        calcdp(ed.first, 0, ed, false);
        str vl1 = max(dp[ed.first][0], dp[ed.first][1]),
            vl2 = str(1, val[ed.first] != val[ed.second]);

        for (int x : edg[ed.first])
            edg[x].erase(find(edg[x].begin(), edg[x].end(), ed.first));
        for (int x : edg[ed.second])
            edg[x].erase(find(edg[x].begin(), edg[x].end(), ed.second));

        for (int x : edg[ed.first]) {
            if (!mrk[x] or x == ed.second)
                continue;
            lst.push_back(x); calcdp(x, 0, ed, true);
            vl2 += max(dp[x][0], dp[x][1]);
        }

        for (int x : edg[ed.second]) {
            if (!mrk[x] or x == ed.first)
                continue;
            lst.push_back(x); calcdp(x, 0, ed, true);
            vl2 += max(dp[x][0], dp[x][1]);
        }

        if (vl1 > vl2) {
            ans += vl1;
            for (int x : edg[ed.first])
                edg[x].push_back(ed.first);
            for (int x : edg[ed.second])
                edg[x].push_back(ed.second);
            solvedp(ed.first, 0, ed, 2);
        } else {
            ans += vl2;
            for (int x : lst)
                solvedp(x, 0, ed, 2);
            sol.push_back(ed);
        }
    }

    cout << ans.x << " " << ans.y << "\n";
    for (pair<int, int> pr : sol)
        cout << pr.first << " " << pr.second << "\n";

    return 0;
}


#include <bits/stdc++.h>
using namespace std;

ifstream in("pairs.in");
ofstream out("pairs.out");

const int DIM = 1e5 + 5;

int nxt[DIM], val[DIM], pos[DIM];

pair<int, int> tdp[DIM][2], cdp[DIM], arr[2][DIM]; deque<int> chn;
bitset<DIM> oki, mrk, ist; vector<pair<int, int>> sol; vector<int> edg[DIM];

pair<int, int> operator + (const pair<int, int> &p1, const pair<int, int> &p2) {
    return pair<int, int>(p1.first + p2.first, p1.second + p2.second);
}

pair<int, int> operator - (const pair<int, int> &p1, const pair<int, int> &p2) {
    return pair<int, int>(p1.first - p2.first, p1.second - p2.second);
}

void calcdp(int x)
{
    mrk[x] = true; pos[x] = 0;
    tdp[x][0] = tdp[x][1] = pair<int, int>(0, 0);

    for (int y : edg[x]) {
        calcdp(y);
        tdp[x][0] = tdp[x][0] + max(tdp[y][0], tdp[y][1]);

        pair<int, int> aux = tdp[y][0] - max(tdp[y][0], tdp[y][1]) +
                             pair<int, int>(1, val[x] != val[y]);
        if (tdp[x][1] < aux)
            tdp[x][1] = aux, pos[x] = y;
    }

    tdp[x][1] = tdp[x][1] + tdp[x][0];
}

int _nr[2];
void solvedp(int x, bool ok, int nr)
{
    if (ok and pos[x])
        arr[nr][++_nr[nr]] = make_pair(x, pos[x]);
    for (int y : edg[x])
        solvedp(y, (ok and y == pos[x]) ? false : true, nr);
}

int main(void)
{
    int n; scanf("%d", &n);
    for (int i = 1; i <= n; ++i) {
        scanf("%d %d", &nxt[i], &val[i]);
        edg[nxt[i]].push_back(i);
    }

    pair<int, int> ans;
    for (int i = 1; i <= n; ++i) if (!mrk[i]) {
        chn.clear();
        for (int x = i; true; x = nxt[x]) {
            chn.push_back(x);

            if (!oki[x])
                oki[x] = true;
            else {
                while (chn.front() != chn.back())
                    oki[chn.front()] = false, chn.pop_front();
                break;
            }
        }

        pair<int, int> pr1, pr2;

        edg[chn[1]].erase(find(edg[chn[1]].begin(), edg[chn[1]].end(), chn[0]));
        calcdp(chn[0]); _nr[0] = 0; solvedp(chn[0], true, 0); edg[chn[1]].push_back(chn[0]);
        pr1 = max(tdp[chn[0]][0], tdp[chn[0]][1]);

        edg[chn[2]].erase(find(edg[chn[2]].begin(), edg[chn[2]].end(), chn[1]));
        calcdp(chn[1]); _nr[1] = 0; solvedp(chn[1], true, 1); edg[chn[2]].push_back(chn[1]);
        pr2 = max(tdp[chn[1]][0], tdp[chn[1]][1]);

        if (pr1 > pr2) {
            ans = ans + pr1;
            for (int i = 1; i <= pr1.first; ++i)
                sol.push_back(arr[0][i]);
        } else {
            ans = ans + pr2;
            for (int i = 1; i <= pr2.first; ++i)
                sol.push_back(arr[1][i]);
        }
    }

    printf("%d %d\n", ans.first, ans.second);
    for (pair<int, int> pr : sol)
        printf("%d %d\n", pr.first, pr.second);

    return 0;
}


#include <bits/stdc++.h>
using namespace std;

ifstream in("pairs.in");
ofstream out("pairs.out");

const int DIM = 1e5 + 5;

struct str
{
    int x, y;
    str(int _x = 0, int _y = 0) {
        x = _x;
        y = _y;
    }

    inline str operator +(const str &a) const {
        return str(x + a.x, y + a.y);
    }

    inline str operator -(const str &a) const {
        return str(x - a.x, y - a.y);
    }

    inline str operator +=(const str &a) {
        return *this = *this + a;
    }

    inline bool operator <(const str &a) const {
        if (x == a.x)
            return y < a.y;
        return x < a.x;
    }

    inline bool operator >(const str &a) const {
        if (x == a.x)
            return y > a.y;
        return x > a.x;
    }

    inline bool operator <=(const str &a) const {
        if (x == a.x)
            return y <= a.y;
        return x < a.x;
    }

    inline bool operator >=(const str &a) const {
        if (x == a.x)
            return y >= a.y;
        return x > a.x;
    }

    inline bool operator ==(const str &a) const {
        if (x == a.x)
            return y == a.y;
        return x == a.x;
    }
} tdp[DIM][2], cdp[DIM];

int nxt[DIM], val[DIM], pos[DIM];

bitset<DIM> oki, mrk, ist;
vector<int> edg[DIM]; deque<int> chn;
vector<pair<int, int>> sol, aux1, aux2;

str calccst(vector<pair<int, int>> &arr)
{
    int cst = 0;
    for (pair<int, int> pr : arr)
        cst += val[pr.first] != val[pr.second];

    return str((int) arr.size(), cst);
}

void calcdp(int x)
{
    vector<int> aux; mrk[x] = true;
    for (int y : edg[x]) if (!oki[y])
        calcdp(y), aux.push_back(y);

    for (int y : aux)
        tdp[x][0] += max(tdp[y][0], tdp[y][1]);

    for (int y : aux) {
        str aux = tdp[x][0] - max(tdp[y][0], tdp[y][1]) +
        tdp[y][0] + str(1, val[x] != val[y]);

        if (tdp[x][1] < aux)
            tdp[x][1] = aux, pos[x] = y;
    }
}

void solvedp(int x, bool ok, vector<pair<int, int>> &arr)
{
    vector<int> aux;
    for (int y : edg[x]) if (!oki[y])
        calcdp(y), aux.push_back(y);

    if (ok and tdp[x][0] >= tdp[x][1])
        ok = false;

    if (!ok) {
        for (int y : aux)
            solvedp(y, true, arr);
    } else {
        arr.push_back(make_pair(x, pos[x]));
        for (int y : aux)
            solvedp(y, y != pos[x], arr);
    }
}

void calccdp(int le, int ri, deque<int> &chn, vector<pair<int, int>> &arr)
{
    for (int i = le; i <= ri; ++i) {
        if (i == le)
            cdp[i] = max(tdp[chn[i]][0], tdp[chn[i]][1]);
        else
        if (i == le + 1)
            cdp[i] = max(max(tdp[chn[i]][0], tdp[chn[i]][1]) + cdp[i - 1],
                         tdp[chn[i - 1]][0] + tdp[chn[i]][0] + str(1, val[chn[i - 1]] != val[chn[i]]));
        else
            cdp[i] = max(max(tdp[chn[i]][0], tdp[chn[i]][1]) + cdp[i - 1],
                         tdp[chn[i - 1]][0] + tdp[chn[i]][0] + str(1, val[chn[i - 1]] != val[chn[i]]) + cdp[i - 2]);
    }

    for (int i = ri; i >= le; ) {
        if (i == le or cdp[i] == max(tdp[chn[i]][0], tdp[chn[i]][1]) + cdp[i - 1])
            solvedp(chn[i], true, arr), i -= 1;
        else {
            solvedp(chn[i - 1], false, arr); solvedp(chn[i], false, arr);
            arr.push_back(make_pair(chn[i - 1], chn[i])); i -= 2;
        }
    }
}

int main(void)
{
    int n; in >> n;
    for (int i = 1; i <= n; ++i) {
        in >> nxt[i] >> val[i];
        edg[nxt[i]].push_back(i);
    }

    for (int i = 1; i <= n; ++i) if (!mrk[i]) {
        chn.clear();
        for (int x = i; true; x = nxt[x]) {
            chn.push_back(x);

            if (!oki[x])
                oki[x] = true;
            else {
                while (chn.front() != chn.back())
                    oki[chn.front()] = false, chn.pop_front();
                break;
            }
        }

        for (int i = 1; i < chn.size(); ++i)
            calcdp(chn[i]);

        aux1.clear(); aux2.clear();
        calccdp(0, (int) chn.size() - 2, chn, aux1),
        calccdp(1, (int) chn.size() - 1, chn, aux2);

        if (calccst(aux1) < calccst(aux2))
            swap(aux1, aux2);
        for (pair<int, int> pr : aux1)
            sol.push_back(pr);
    }

    out << sol.size() << " " << calccst(sol).y << "\n";
    for (pair<int, int> pr : sol)
        out << pr.first << " " << pr.second << "\n";

    return 0;
}


#include <bits/stdc++.h>
using namespace std;

ifstream in("pairs.in");
ofstream out("pairs.out");

const int DIM = 1e5 + 5;

int nxt[DIM], val[DIM], pos[DIM];

bitset<DIM> oki, mrk, ist; vector<pair<int, int>> sol, aux1, aux2;
vector<int> edg[DIM]; deque<int> chn; pair<int, int> tdp[DIM][2], cdp[DIM];

pair<int, int> operator + (const pair<int, int> &p1, const pair<int, int> &p2) {
    return pair<int, int>(p1.first + p2.first, p1.second + p2.second);
}

pair<int, int> operator - (const pair<int, int> &p1, const pair<int, int> &p2) {
    return pair<int, int>(p1.first - p2.first, p1.second - p2.second);
}

pair<int, int> calccst(vector<pair<int, int>> &arr)
{
    int cst = 0;
    for (pair<int, int> pr : arr)
        cst += val[pr.first] != val[pr.second];

    return pair<int, int>((int) arr.size(), cst);
}

void calcdp(int x)
{
    mrk[x] = true;
    tdp[x][0] = tdp[x][1] = pair<int, int>(0, 0);

    vector<int> aux;
    for (int y : edg[x])
        calcdp(y), aux.push_back(y);

    for (int y : aux)
        tdp[x][0] = tdp[x][0] + max(tdp[y][0], tdp[y][1]);

    for (int y : aux) {
        pair<int, int> aux = tdp[x][0] - max(tdp[y][0], tdp[y][1]) +
                  tdp[y][0] + pair<int, int>(1, val[x] != val[y]);

        if (tdp[x][1] < aux)
            tdp[x][1] = aux, pos[x] = y;
    }
}

void solvedp(int x, bool ok, vector<pair<int, int>> &arr)
{
    vector<int> aux;
    for (int y : edg[x])
        calcdp(y), aux.push_back(y);

    if (ok and tdp[x][0] >= tdp[x][1])
        ok = false;

    if (!ok) {
        for (int y : aux)
            solvedp(y, true, arr);
    } else {
        arr.push_back(make_pair(x, pos[x]));
        for (int y : aux)
            solvedp(y, y != pos[x], arr);
    }
}

int main(void)
{
    int n; scanf("%d", &n);
    for (int i = 1; i <= n; ++i) {
        scanf("%d %d", &nxt[i], &val[i]);
        edg[nxt[i]].push_back(i);
    }

    for (int i = 1; i <= n; ++i) if (!mrk[i]) {
        chn.clear();
        for (int x = i; true; x = nxt[x]) {
            chn.push_back(x);

            if (!oki[x])
                oki[x] = true;
            else {
                while (chn.front() != chn.back())
                    oki[chn.front()] = false, chn.pop_front();
                break;
            }
        }

        edg[chn[1]].erase(find(edg[chn[1]].begin(), edg[chn[1]].end(), chn[0]));
        calcdp(chn[0]); aux1.clear(); solvedp(chn[0], true, aux1); edg[chn[1]].push_back(chn[0]);

        edg[chn[2]].erase(find(edg[chn[2]].begin(), edg[chn[2]].end(), chn[1]));
        calcdp(chn[1]); aux2.clear(); solvedp(chn[1], true, aux2); edg[chn[2]].push_back(chn[1]);

        if (calccst(aux1) < calccst(aux2))
            swap(aux1, aux2);
        for (pair<int, int> pr : aux1)
            sol.push_back(pr);
    }

    printf("%d %d\n", (int) sol.size(), calccst(sol).second);
    for (pair<int, int> pr : sol)
        printf("%d %d\n", pr.first, pr.second);

    return 0;
}


#include <bits/stdc++.h>
using namespace std;

ifstream in("pairs.in");
ofstream out("pairs.out");

const int DIM = 1e5 + 5;

int nxt[DIM], val[DIM], pos[DIM];

bitset<DIM> oki, mrk, ist; vector<pair<int, int>> sol, aux1, aux2;
vector<int> edg[DIM]; deque<int> chn; pair<int, int> tdp[DIM][2], cdp[DIM];

pair<int, int> operator + (const pair<int, int> &p1, const pair<int, int> &p2) {
    return pair<int, int>(p1.first + p2.first, p1.second + p2.second);
}

pair<int, int> operator - (const pair<int, int> &p1, const pair<int, int> &p2) {
    return pair<int, int>(p1.first - p2.first, p1.second - p2.second);
}

pair<int, int> calccst(vector<pair<int, int>> &arr)
{
    int cst = 0;
    for (pair<int, int> pr : arr)
        cst += val[pr.first] != val[pr.second];

    return pair<int, int>((int) arr.size(), cst);
}

void calcdp(int x)
{
    mrk[x] = true;
    tdp[x][0] = tdp[x][1] = pair<int, int>(0, 0);

    vector<int> aux;
    for (int y : edg[x])
        calcdp(y), aux.push_back(y);

    for (int y : aux)
        tdp[x][0] = tdp[x][0] + max(tdp[y][0], tdp[y][1]);

    for (int y : aux) {
        pair<int, int> aux = tdp[x][0] - max(tdp[y][0], tdp[y][1]) +
                  tdp[y][0] + pair<int, int>(1, val[x] != val[y]);

        if (tdp[x][1] < aux)
            tdp[x][1] = aux, pos[x] = y;
    }
}

void solvedp(int x, bool ok, vector<pair<int, int>> &arr)
{
    vector<int> aux;
    for (int y : edg[x])
        calcdp(y), aux.push_back(y);

    if (ok and tdp[x][0] >= tdp[x][1])
        ok = false;

    if (!ok) {
        for (int y : aux)
            solvedp(y, true, arr);
    } else {
        arr.push_back(make_pair(x, pos[x]));
        for (int y : aux)
            solvedp(y, y != pos[x], arr);
    }
}

int main(void)
{
    int n; cin >> n;
    for (int i = 1; i <= n; ++i) {
        cin >> nxt[i] >> val[i];
        edg[nxt[i]].push_back(i);
    }

    for (int i = 1; i <= n; ++i) if (!mrk[i]) {
        chn.clear();
        for (int x = i; true; x = nxt[x]) {
            chn.push_back(x);

            if (!oki[x])
                oki[x] = true;
            else {
                while (chn.front() != chn.back())
                    oki[chn.front()] = false, chn.pop_front();
                break;
            }
        }

        edg[chn[1]].erase(find(edg[chn[1]].begin(), edg[chn[1]].end(), chn[0]));
        calcdp(chn[0]); aux1.clear(); solvedp(chn[0], true, aux1); edg[chn[1]].push_back(chn[0]);

        edg[chn[2]].erase(find(edg[chn[2]].begin(), edg[chn[2]].end(), chn[1]));
        calcdp(chn[1]); aux2.clear(); solvedp(chn[1], true, aux2); edg[chn[2]].push_back(chn[1]);

        if (calccst(aux1) < calccst(aux2))
            swap(aux1, aux2);
        for (pair<int, int> pr : aux1)
            sol.push_back(pr);
    }

    cout << sol.size() << " " << calccst(sol).second << "\n";
    for (pair<int, int> pr : sol)
        cout << pr.first << " " << pr.second << "\n";

    return 0;
}


#include <bits/stdc++.h>
using namespace std;

ifstream in("pairs.in");
ofstream out("pairs.out");

const int DIM = 1e5 + 5;
const int INF = 1e9 + 7;

int val[DIM], fth[DIM], lev[DIM], pos[DIM];

vector<int> edg[DIM], stk, aux, lst;
bitset<DIM> oki, mrk; vector<pair<int, int>> sol;

struct str
{
    int x, y;
    str(int _x = 0, int _y = 0) {
        x = _x;
        y = _y;
    }

    inline str operator +(const str &a) const {
        return str(x + a.x, y + a.y);
    }

    inline str operator -(const str &a) const {
        return str(x - a.x, y - a.y);
    }

    inline str operator +=(const str &a) {
        return *this = *this + a;
    }

    inline bool operator <(const str &a) const {
        if (x == a.x)
            return y < a.y;
        return x < a.x;
    }

    inline bool operator >(const str &a) const {
        if (x == a.x)
            return y > a.y;
        return x > a.x;
    }

    inline bool operator <=(const str &a) const {
        if (x == a.x)
            return y <= a.y;
        return x < a.x;
    }

    inline bool operator >=(const str &a) const {
        if (x == a.x)
            return y >= a.y;
        return x > a.x;
    }
} dp[DIM][2];

void dfs(int x, int f, pair<int, int> &ed)
{
    stk.push_back(x); fth[x] = f; bool ok = false;
    oki[x] = mrk[x] = true; lev[x] = lev[f] + 1;

    for (int y : edg[x]) {
        if (y == f) {
            if (ok)
                ed = make_pair(x, y);
            ok = true; continue;
        }

        if (!oki[y])
            dfs(y, x, ed);
        else
        if (lev[y] < lev[x]) {
            for (int z = x; z != fth[y]; z = fth[z])
                aux.push_back(z);
            ed = make_pair(x, y);
        }
    }

    stk.pop_back();
}

void calcdp(int x, int f, pair<int, int> ed, bool ok)
{
    if (ok and (x == ed.first or x == ed.second))
        return;
    if (ok)
        mrk[x] = false;

    vector<int> aux; vector<str> dpl, dpr;
    dp[x][0] = str(0, 0); dp[x][1] = str(-INF, -INF);

    for (int y : edg[x]) {
        if (y == f or (x == ed.first and y == ed.second)
                   or (y == ed.first and x == ed.second))
            continue;

        calcdp(y, x, ed, ok);
        if (!ok or (y != ed.first and y != ed.second))
            aux.push_back(y);
    }

    for (int y : aux)
        dp[x][0] += max(dp[y][0], dp[y][1]);

    dpl.resize(aux.size());
    for (int i = 0; i < aux.size(); ++i) {
        dpl[i] = max(dp[aux[i]][0], dp[aux[i]][1]);

        if (i - 1 >= 0)
            dpl[i] += dpl[i - 1];
    }

    dpr.resize(aux.size());
    for (int i = (int) aux.size() - 1; i >= 0; --i) {
        dpr[i] = max(dp[aux[i]][0], dp[aux[i]][1]);

        if (i + 1 < aux.size())
            dpr[i] += dpr[i + 1];
    }

    for (int i = 0; i < aux.size(); ++i) {
        str cns = str(1, val[x] != val[aux[i]]) + dp[aux[i]][0];

        if (i - 1 >= 0) cns += dpl[i - 1];
        if (i + 1 < aux.size()) cns += dpr[i + 1];

        if (dp[x][1] < cns)
            dp[x][1] = cns, pos[x] = aux[i];
    }
}

// 0 - blocked, 1 - must take, 2 - 0 or 1
void solvedp(int x, int f, pair<int, int> ed, bool ok, int msk)
{
    if (ok and (x == ed.first or x == ed.second))
        return;
    if (ok)
        mrk[x] = false;

    vector<int> aux;
    for (int y : edg[x]) {
        if (y == f or (x == ed.first and y == ed.second)
                   or (y == ed.first and x == ed.second))
            continue;

        if (!ok or (y != ed.first and y != ed.second))
            aux.push_back(y);
    }

    if (!msk or (msk == 2 and dp[x][0] >= dp[x][1])) {
        for (int y : aux)
            solvedp(y, x, ed, ok, 2);
    } else {
        sol.push_back(make_pair(x, pos[x]));
        for (int y : aux) if (y != pos[x])
            solvedp(y, x, ed, ok, 2);
        solvedp(pos[x], x, ed, ok, 0);
    }
}

int main(void)
{
    int n;
    cin >> n;

    for (int i = 1; i <= n; ++i) {
        int x;
        cin >> x >> val[i];

        edg[i].push_back(x);
        edg[x].push_back(i);
    }

    str ans;
    for (int i = 1; i <= n; ++i) {
        if (oki[i])
            continue;
        pair<int, int> ed;
        aux.clear(); lst.clear(); dfs(i, 0, ed);

        calcdp(ed.first, 0, ed, false);
        str vl1 = max(dp[ed.first][0], dp[ed.first][1]),
            vl2 = str(1, val[ed.first] != val[ed.second]);

        for (int x : edg[ed.first]) {
            if (!mrk[x] or x == ed.second)
                continue;

            lst.push_back(x);
            calcdp(x, 0, ed, true);
            vl2 += max(dp[x][0], dp[x][1]);
        }

        for (int x : edg[ed.second]) {
            if (!mrk[x] or x == ed.first)
                continue;

            lst.push_back(x);
            calcdp(x, 0, ed, true);
            vl2 += max(dp[x][0], dp[x][1]);
        }

        if (vl1 > vl2) {
            ans += vl1;
            solvedp(ed.first, 0, ed, false, 2);
        } else {
            ans += vl2;
            for (int x : lst)
                solvedp(x, 0, ed, true, 2);
            sol.push_back(ed);
        }
    }

    cout << ans.x << " " << ans.y << "\n";
    for (pair<int, int> pr : sol)
        cout << pr.first << " " << pr.second << "\n";

    return 0;
}


#include <bits/stdc++.h>
using namespace std;

ifstream in("pairs.in");
ofstream out("pairs.out");

const int DIM = 1e5 + 5;

int nxt[DIM], val[DIM], pos[DIM];

bitset<DIM> oki, mrk, ist; vector<pair<int, int>> sol, aux1, aux2;
vector<int> edg[DIM]; deque<int> chn; pair<int, int> tdp[DIM][2], cdp[DIM];

pair<int, int> operator + (const pair<int, int> &p1, const pair<int, int> &p2) {
    return pair<int, int>(p1.first + p2.first, p1.second + p2.second);
}

pair<int, int> operator - (const pair<int, int> &p1, const pair<int, int> &p2) {
    return pair<int, int>(p1.first - p2.first, p1.second - p2.second);
}

pair<int, int> calccst(vector<pair<int, int>> &arr)
{
    int cst = 0;
    for (pair<int, int> pr : arr)
        cst += val[pr.first] != val[pr.second];

    return pair<int, int>((int) arr.size(), cst);
}

void calcdp(int x)
{
    vector<int> aux; mrk[x] = true;
    for (int y : edg[x])
        calcdp(y), aux.push_back(y);

    for (int y : aux)
        tdp[x][0] = tdp[x][0] + max(tdp[y][0], tdp[y][1]);

    for (int y : aux) {
        pair<int, int> aux = tdp[x][0] - max(tdp[y][0], tdp[y][1]) +
                  tdp[y][0] + pair<int, int>(1, val[x] != val[y]);

        if (tdp[x][1] < aux)
            tdp[x][1] = aux, pos[x] = y;
    }
}

void solvedp(int x, bool ok, vector<pair<int, int>> &arr)
{
    vector<int> aux;
    for (int y : edg[x])
        calcdp(y), aux.push_back(y);

    if (ok and tdp[x][0] >= tdp[x][1])
        ok = false;

    if (!ok) {
        for (int y : aux)
            solvedp(y, true, arr);
    } else {
        arr.push_back(make_pair(x, pos[x]));
        for (int y : aux)
            solvedp(y, y != pos[x], arr);
    }
}

int main(void)
{
    int n; cin >> n;
    for (int i = 1; i <= n; ++i) {
        cin >> nxt[i] >> val[i];
        edg[nxt[i]].push_back(i);
    }

    for (int i = 1; i <= n; ++i) if (!mrk[i]) {
        chn.clear();
        for (int x = i; true; x = nxt[x]) {
            chn.push_back(x);

            if (!oki[x])
                oki[x] = true;
            else {
                while (chn.front() != chn.back())
                    oki[chn.front()] = false, chn.pop_front();
                break;
            }
        }

        edg[chn[1]].erase(find(edg[chn[1]].begin(), edg[chn[1]].end(), chn[0]));
        calcdp(chn[0]); aux1.clear(); solvedp(chn[0], true, aux1); edg[chn[1]].push_back(chn[0]);

        edg[chn[2]].erase(find(edg[chn[2]].begin(), edg[chn[2]].end(), chn[1]));
        calcdp(chn[1]); aux2.clear(); solvedp(chn[1], true, aux2); edg[chn[2]].push_back(chn[1]);

        if (calccst(aux1) < calccst(aux2))
            swap(aux1, aux2);
        for (pair<int, int> pr : aux1)
            sol.push_back(pr);
    }

    cout << sol.size() << " " << calccst(sol).second << "\n";
    for (pair<int, int> pr : sol)
        cout << pr.first << " " << pr.second << "\n";

    return 0;
}


#include <bits/stdc++.h>
using namespace std;

ifstream in("pairs.in");
ofstream out("pairs.out");

const int DIM = 1e5 + 5;
const int INF = 1e9 + 7;

int val[DIM], fth[DIM], lev[DIM], pos[DIM];

vector<int> edg[DIM], stk, aux, lst;
bitset<DIM> oki, mrk; vector<pair<int, int>> sol;

struct str
{
    int x, y;
    str(int _x = 0, int _y = 0) {
        x = _x;
        y = _y;
    }

    inline str operator +(const str &a) const {
        return str(x + a.x, y + a.y);
    }

    inline str operator -(const str &a) const {
        return str(x - a.x, y - a.y);
    }

    inline str operator +=(const str &a) {
        return *this = *this + a;
    }

    inline bool operator <(const str &a) const {
        if (x == a.x)
            return y < a.y;
        return x < a.x;
    }

    inline bool operator >(const str &a) const {
        if (x == a.x)
            return y > a.y;
        return x > a.x;
    }

    inline bool operator <=(const str &a) const {
        if (x == a.x)
            return y <= a.y;
        return x < a.x;
    }

    inline bool operator >=(const str &a) const {
        if (x == a.x)
            return y >= a.y;
        return x > a.x;
    }
} dp[DIM][2];

void dfs(int x, int f, pair<int, int> &ed)
{
    stk.push_back(x); fth[x] = f; bool ok = false;
    oki[x] = mrk[x] = true; lev[x] = lev[f] + 1;

    for (int y : edg[x]) {
        if (y == f) {
            if (ok)
                ed = make_pair(x, y);
            ok = true; continue;
        }

        if (!oki[y])
            dfs(y, x, ed);
        else
        if (lev[y] < lev[x]) {
            for (int z = x; z != fth[y]; z = fth[z])
                aux.push_back(z);
            ed = make_pair(x, y);
        }
    }

    stk.pop_back();
}

void calcdp(int x, int f, pair<int, int> ed, bool ok)
{
    if (ok)
        mrk[x] = false;

    vector<int> aux; vector<str> dpl, dpr;
    dp[x][0] = str(0, 0); dp[x][1] = str(-INF, -INF);

    for (int y : edg[x]) {
        if (y == f or (x == ed.first and y == ed.second)
                   or (y == ed.first and x == ed.second))
            continue;
        calcdp(y, x, ed, ok); aux.push_back(y);
    }

    for (int y : aux)
        dp[x][0] += max(dp[y][0], dp[y][1]);

    dpl.resize(aux.size());
    for (int i = 0; i < aux.size(); ++i) {
        dpl[i] = max(dp[aux[i]][0], dp[aux[i]][1]);

        if (i - 1 >= 0)
            dpl[i] += dpl[i - 1];
    }

    dpr.resize(aux.size());
    for (int i = (int) aux.size() - 1; i >= 0; --i) {
        dpr[i] = max(dp[aux[i]][0], dp[aux[i]][1]);

        if (i + 1 < aux.size())
            dpr[i] += dpr[i + 1];
    }

    for (int i = 0; i < aux.size(); ++i) {
        str cns = str(1, val[x] != val[aux[i]]) + dp[aux[i]][0];

        if (i - 1 >= 0) cns += dpl[i - 1];
        if (i + 1 < aux.size()) cns += dpr[i + 1];

        if (dp[x][1] < cns)
            dp[x][1] = cns, pos[x] = aux[i];
    }
}

// 0 - blocked, 1 - must take, 2 - 0 or 1
void solvedp(int x, int f, pair<int, int> ed, int msk)
{
    vector<int> aux;
    for (int y : edg[x]) {
        if (y == f or (x == ed.first and y == ed.second)
                   or (y == ed.first and x == ed.second))
            continue;

        aux.push_back(y);
    }

    if (!msk or (msk == 2 and dp[x][0] >= dp[x][1])) {
        for (int y : aux)
            solvedp(y, x, ed, 2);
    } else {
        sol.push_back(make_pair(x, pos[x]));
        for (int y : aux) if (y != pos[x])
            solvedp(y, x, ed, 2);
        solvedp(pos[x], x, ed, 0);
    }
}

int main(void)
{
    int n;
    cin >> n;

    for (int i = 1; i <= n; ++i) {
        int x;
        cin >> x >> val[i];

        edg[i].push_back(x);
        edg[x].push_back(i);
    }

    str ans;
    for (int i = 1; i <= n; ++i) {
        if (oki[i])
            continue;
        pair<int, int> ed;
        aux.clear(); lst.clear(); dfs(i, 0, ed);

        assert(ed != make_pair(0, 0));

        calcdp(ed.first, 0, ed, false);
        str vl1 = max(dp[ed.first][0], dp[ed.first][1]),
            vl2 = str(1, val[ed.first] != val[ed.second]);

        for (int x : edg[ed.first])
            edg[x].erase(find(edg[x].begin(), edg[x].end(), ed.first));
        for (int x : edg[ed.second])
            edg[x].erase(find(edg[x].begin(), edg[x].end(), ed.second));

        for (int x : edg[ed.first]) {
            if (!mrk[x] or x == ed.second)
                continue;
            lst.push_back(x); calcdp(x, 0, ed, true);
            vl2 += max(dp[x][0], dp[x][1]);
        }

        for (int x : edg[ed.second]) {
            if (!mrk[x] or x == ed.first)
                continue;
            lst.push_back(x); calcdp(x, 0, ed, true);
            vl2 += max(dp[x][0], dp[x][1]);
        }

        if (vl1 > vl2) {
            ans += vl1;
            for (int x : edg[ed.first])
                edg[x].push_back(ed.first);
            for (int x : edg[ed.second])
                edg[x].push_back(ed.second);
            solvedp(ed.first, 0, ed, 2);
        } else {
            ans += vl2;
            for (int x : lst)
                solvedp(x, 0, ed, 2);
            sol.push_back(ed);
        }
    }

    cout << ans.x << " " << ans.y << "\n";
    for (pair<int, int> pr : sol)
        cout << pr.first << " " << pr.second << "\n";

    return 0;
}


#include <bits/stdc++.h>
using namespace std;

ifstream in("pairs.in");
ofstream out("pairs.out");

const int DIM = 1e5 + 5;
const int INF = 1e9 + 7;

int val[DIM], fth[DIM], lev[DIM], pos[DIM];

vector<int> edg[DIM], stk, aux, lst;
bitset<DIM> oki, mrk; vector<pair<int, int>> sol;

struct str
{
    int x, y;
    str(int _x = 0, int _y = 0) {
        x = _x;
        y = _y;
    }

    inline str operator +(const str &a) const {
        return str(x + a.x, y + a.y);
    }

    inline str operator -(const str &a) const {
        return str(x - a.x, y - a.y);
    }

    inline str operator +=(const str &a) {
        return *this = *this + a;
    }

    inline bool operator <(const str &a) const {
        if (x == a.x)
            return y < a.y;
        return x < a.x;
    }

    inline bool operator >(const str &a) const {
        if (x == a.x)
            return y > a.y;
        return x > a.x;
    }

    inline bool operator <=(const str &a) const {
        if (x == a.x)
            return y <= a.y;
        return x < a.x;
    }

    inline bool operator >=(const str &a) const {
        if (x == a.x)
            return y >= a.y;
        return x > a.x;
    }
} dp[DIM][2];

void dfs(int x, int f, pair<int, int> &ed)
{
    stk.push_back(x); fth[x] = f;
    oki[x] = mrk[x] = true; lev[x] = lev[f] + 1;

    for (int y : edg[x]) {
        if (y == f)
            continue;

        if (!oki[y])
            dfs(y, x, ed);
        else
        if (lev[y] < lev[x]) {
            for (int z = x; z != fth[y]; z = fth[z])
                aux.push_back(z);
            ed = make_pair(x, y);
        }
    }

    stk.pop_back();
}

void calcdp(int x, int f, pair<int, int> ed, bool ok)
{
    if (ok and (x == ed.first or x == ed.second))
        return;
    if (ok)
        mrk[x] = false;

    vector<int> aux; vector<str> dpl, dpr;
    dp[x][0] = str(0, 0); dp[x][1] = str(-INF, -INF);

    for (int y : edg[x]) {
        if (y == f or (x == ed.first and y == ed.second)
                   or (y == ed.first and x == ed.second))
            continue;

        calcdp(y, x, ed, ok);
        if (!ok or (y != ed.first and y != ed.second))
            aux.push_back(y);
    }

    for (int y : aux)
        dp[x][0] += max(dp[y][0], dp[y][1]);

    dpl.resize(aux.size());
    for (int i = 0; i < aux.size(); ++i) {
        dpl[i] = max(dp[aux[i]][0], dp[aux[i]][1]);

        if (i - 1 >= 0)
            dpl[i] += dpl[i - 1];
    }

    dpr.resize(aux.size());
    for (int i = (int) aux.size() - 1; i >= 0; --i) {
        dpr[i] = max(dp[aux[i]][0], dp[aux[i]][1]);

        if (i + 1 < aux.size())
            dpr[i] += dpr[i + 1];
    }

    for (int i = 0; i < aux.size(); ++i) {
        str cns = str(1, val[x] != val[aux[i]]) + dp[aux[i]][0];

        if (i - 1 >= 0) cns += dpl[i - 1];
        if (i + 1 < aux.size()) cns += dpr[i + 1];

        if (dp[x][1] < cns)
            dp[x][1] = cns, pos[x] = aux[i];
    }
}

// 0 - blocked, 1 - must take, 2 - 0 or 1
void solvedp(int x, int f, pair<int, int> ed, bool ok, int msk)
{
    if (ok and (x == ed.first or x == ed.second))
        return;
    if (ok)
        mrk[x] = false;

    vector<int> aux;
    for (int y : edg[x]) {
        if (y == f or (x == ed.first and y == ed.second)
                   or (y == ed.first and x == ed.second))
            continue;

        if (!ok or (y != ed.first and y != ed.second))
            aux.push_back(y);
    }

    if (!msk or (msk == 2 and dp[x][0] >= dp[x][1])) {
        for (int y : aux)
            solvedp(y, x, ed, ok, 2);
    } else {
        sol.push_back(make_pair(x, pos[x]));
        for (int y : aux) if (y != pos[x])
            solvedp(y, x, ed, ok, 2);
        solvedp(pos[x], x, ed, ok, 0);
    }
}

int main(void)
{
    int n;
    cin >> n;

    for (int i = 1; i <= n; ++i) {
        int x;
        cin >> x >> val[i];

        edg[i].push_back(x);
        edg[x].push_back(i);
    }

    str ans;
    for (int i = 1; i <= n; ++i) {
        if (oki[i])
            continue;
        pair<int, int> ed;
        aux.clear(); lst.clear(); dfs(i, 0, ed);

        if (ed == make_pair(0, 0)) {
            calcdp(i, 0, ed, false); solvedp(i, 0, ed, false, 2);
            ans += max(dp[i][0], dp[i][1]);
            continue;
        }

        calcdp(ed.first, 0, ed, false);
        str vl1 = max(dp[ed.first][0], dp[ed.first][1]),
            vl2 = str(1, val[ed.first] != val[ed.second]);

        for (int x : edg[ed.first]) {
            if (!mrk[x] or x == ed.second)
                continue;

            lst.push_back(x);
            calcdp(x, 0, ed, true);
            vl2 += max(dp[x][0], dp[x][1]);
        }

        for (int x : edg[ed.second]) {
            if (!mrk[x] or x == ed.first)
                continue;

            lst.push_back(x);
            calcdp(x, 0, ed, true);
            vl2 += max(dp[x][0], dp[x][1]);
        }

        if (vl1 > vl2) {
            ans += vl1;
            solvedp(ed.first, 0, ed, false, 2);
        } else {
            ans += vl2;
            for (int x : lst)
                solvedp(x, 0, ed, true, 2);
            sol.push_back(ed);
        }
    }

    cout << ans.x << " " << ans.y << "\n";
    for (pair<int, int> pr : sol)
        cout << pr.first << " " << pr.second << "\n";

    return 0;
}


#include <bits/stdc++.h>
using namespace std;

ifstream in("pairs.in");
ofstream out("pairs.out");

const int DIM = 1e5 + 5;

int nxt[DIM], val[DIM], pos[DIM];

bitset<DIM> oki, mrk, ist; vector<pair<int, int>> sol, aux1, aux2;
vector<int> edg[DIM]; deque<int> chn; pair<int, int> tdp[DIM][2], cdp[DIM];

pair<int, int> operator + (const pair<int, int> &p1, const pair<int, int> &p2) {
    return pair<int, int>(p1.first + p2.first, p1.second + p2.second);
}

pair<int, int> operator - (const pair<int, int> &p1, const pair<int, int> &p2) {
    return pair<int, int>(p1.first - p2.first, p1.second - p2.second);
}

pair<int, int> calccst(vector<pair<int, int>> &arr)
{
    int cst = 0;
    for (pair<int, int> pr : arr)
        cst += val[pr.first] != val[pr.second];

    return pair<int, int>((int) arr.size(), cst);
}

void calcdp(int x)
{
    vector<int> aux; mrk[x] = true;
    for (int y : edg[x]) if (!oki[y])
        calcdp(y), aux.push_back(y);

    for (int y : aux)
        tdp[x][0] = tdp[x][0] + max(tdp[y][0], tdp[y][1]);

    for (int y : aux) {
        pair<int, int> aux = tdp[x][0] - max(tdp[y][0], tdp[y][1]) +
                  tdp[y][0] + pair<int, int>(1, val[x] != val[y]);

        if (tdp[x][1] < aux)
            tdp[x][1] = aux, pos[x] = y;
    }
}

void solvedp(int x, bool ok, vector<pair<int, int>> &arr)
{
    vector<int> aux;
    for (int y : edg[x]) if (!oki[y])
        calcdp(y), aux.push_back(y);

    if (ok and tdp[x][0] >= tdp[x][1])
        ok = false;

    if (!ok) {
        for (int y : aux)
            solvedp(y, true, arr);
    } else {
        arr.push_back(make_pair(x, pos[x]));
        for (int y : aux)
            solvedp(y, y != pos[x], arr);
    }
}

void calccdp(int le, int ri, deque<int> &chn, vector<pair<int, int>> &arr)
{
    for (int i = le; i <= ri; ++i) {
        if (i == le)
            cdp[i] = max(tdp[chn[i]][0], tdp[chn[i]][1]);
        else
        if (i == le + 1)
            cdp[i] = max(max(tdp[chn[i]][0], tdp[chn[i]][1]) + cdp[i - 1],
                         tdp[chn[i - 1]][0] + tdp[chn[i]][0] + pair<int, int>(1, val[chn[i - 1]] != val[chn[i]]));
        else
            cdp[i] = max(max(tdp[chn[i]][0], tdp[chn[i]][1]) + cdp[i - 1],
                         tdp[chn[i - 1]][0] + tdp[chn[i]][0] + pair<int, int>(1, val[chn[i - 1]] != val[chn[i]]) + cdp[i - 2]);
    }

    for (int i = ri; i >= le; ) {
        if (i == le or cdp[i] == max(tdp[chn[i]][0], tdp[chn[i]][1]) + cdp[i - 1])
            solvedp(chn[i], true, arr), i -= 1;
        else {
            solvedp(chn[i - 1], false, arr); solvedp(chn[i], false, arr);
            arr.push_back(make_pair(chn[i - 1], chn[i])); i -= 2;
        }
    }
}

int main(void)
{
    int n; cin >> n;
    for (int i = 1; i <= n; ++i) {
        cin >> nxt[i] >> val[i];
        edg[nxt[i]].push_back(i);
    }

    for (int i = 1; i <= n; ++i) if (!mrk[i]) {
        chn.clear();
        for (int x = i; true; x = nxt[x]) {
            chn.push_back(x);

            if (!oki[x])
                oki[x] = true;
            else {
                while (chn.front() != chn.back())
                    oki[chn.front()] = false, chn.pop_front();
                break;
            }
        }

        for (int i = 1; i < chn.size(); ++i)
            calcdp(chn[i]);

        aux1.clear(); aux2.clear();
        calccdp(0, (int) chn.size() - 2, chn, aux1),
        calccdp(1, (int) chn.size() - 1, chn, aux2);

        if (calccst(aux1) < calccst(aux2))
            swap(aux1, aux2);
        for (pair<int, int> pr : aux1)
            sol.push_back(pr);
    }

    cout << sol.size() << " " << calccst(sol).second << "\n";
    for (pair<int, int> pr : sol)
        cout << pr.first << " " << pr.second << "\n";

    return 0;
}


#include <bits/stdc++.h>
using namespace std;

ifstream in("pairs.in");
ofstream out("pairs.out");

const int DIM = 1e5 + 5;

struct str
{
    int x, y;
    str(int _x = 0, int _y = 0) {
        x = _x;
        y = _y;
    }

    inline str operator +(const str &a) const {
        return str(x + a.x, y + a.y);
    }

    inline str operator -(const str &a) const {
        return str(x - a.x, y - a.y);
    }

    inline str operator +=(const str &a) {
        return *this = *this + a;
    }

    inline bool operator <(const str &a) const {
        if (x == a.x)
            return y < a.y;
        return x < a.x;
    }

    inline bool operator >(const str &a) const {
        if (x == a.x)
            return y > a.y;
        return x > a.x;
    }

    inline bool operator <=(const str &a) const {
        if (x == a.x)
            return y <= a.y;
        return x < a.x;
    }

    inline bool operator >=(const str &a) const {
        if (x == a.x)
            return y >= a.y;
        return x > a.x;
    }

    inline bool operator ==(const str &a) const {
        if (x == a.x)
            return y == a.y;
        return x == a.x;
    }
} tdp[DIM][2], cdp[DIM];

int nxt[DIM], val[DIM], pos[DIM];

bitset<DIM> oki, mrk, ist;
vector<int> edg[DIM]; deque<int> chn;
vector<pair<int, int>> sol, aux1, aux2;

str calccst(vector<pair<int, int>> &arr)
{
    int cst = 0;
    for (pair<int, int> pr : arr)
        cst += val[pr.first] != val[pr.second];

    return str((int) arr.size(), cst);
}

void calcdp(int x)
{
    vector<int> aux; mrk[x] = true;
    for (int y : edg[x]) if (!oki[y])
        calcdp(y), aux.push_back(y);

    for (int y : aux)
        tdp[x][0] += max(tdp[y][0], tdp[y][1]);

    for (int y : aux) {
        str aux = tdp[x][0] - max(tdp[y][0], tdp[y][1]) +
        tdp[y][0] + str(1, val[x] != val[y]);

        if (tdp[x][1] < aux)
            tdp[x][1] = aux, pos[x] = y;
    }
}

void solvedp(int x, bool ok, vector<pair<int, int>> &arr)
{
    vector<int> aux;
    for (int y : edg[x]) if (!oki[y])
        calcdp(y), aux.push_back(y);

    if (ok and tdp[x][0] >= tdp[x][1])
        ok = false;

    if (!ok) {
        for (int y : aux)
            solvedp(y, true, arr);
    } else {
        arr.push_back(make_pair(x, pos[x]));
        for (int y : aux)
            solvedp(y, y != pos[x], arr);
    }
}

void calccdp(int le, int ri, deque<int> &chn, vector<pair<int, int>> &arr)
{
    for (int i = le; i <= ri; ++i) {
        if (i == le)
            cdp[i] = max(tdp[chn[i]][0], tdp[chn[i]][1]);
        else
        if (i == le + 1)
            cdp[i] = max(max(tdp[chn[i]][0], tdp[chn[i]][1]) + cdp[i - 1],
                         tdp[chn[i - 1]][0] + tdp[chn[i]][0] + str(1, val[chn[i - 1]] != val[chn[i]]));
        else
            cdp[i] = max(max(tdp[chn[i]][0], tdp[chn[i]][1]) + cdp[i - 1],
                         tdp[chn[i - 1]][0] + tdp[chn[i]][0] + str(1, val[chn[i - 1]] != val[chn[i]]) + cdp[i - 2]);
    }

    for (int i = ri; i >= le; ) {
        if (i == le or cdp[i] == max(tdp[chn[i]][0], tdp[chn[i]][1]) + cdp[i - 1])
            solvedp(chn[i], true, arr), i -= 1;
        else {
            solvedp(chn[i - 1], false, arr); solvedp(chn[i], false, arr);
            arr.push_back(make_pair(chn[i - 1], chn[i])); i -= 2;
        }
    }
}

int main(void)
{
    int n; cin >> n;
    for (int i = 1; i <= n; ++i) {
        cin >> nxt[i] >> val[i];
        edg[nxt[i]].push_back(i);
    }

    for (int i = 1; i <= n; ++i) if (!mrk[i]) {
        chn.clear();
        for (int x = i; true; x = nxt[x]) {
            chn.push_back(x);

            if (!oki[x])
                oki[x] = true;
            else {
                while (chn.front() != chn.back())
                    oki[chn.front()] = false, chn.pop_front();
                break;
            }
        }

        for (int i = 1; i < chn.size(); ++i)
            calcdp(chn[i]);

        aux1.clear(); aux2.clear();
        calccdp(0, (int) chn.size() - 2, chn, aux1),
        calccdp(1, (int) chn.size() - 1, chn, aux2);

        if (calccst(aux1) < calccst(aux2))
            swap(aux1, aux2);
        for (pair<int, int> pr : aux1)
            sol.push_back(pr);
    }

    cout << sol.size() << " " << calccst(sol).y << "\n";
    for (pair<int, int> pr : sol)
        cout << pr.first << " " << pr.second << "\n";

    return 0;
}


#include <bits/stdc++.h>
using namespace std;

ifstream in("pairs.in");
ofstream out("pairs.out");

const int DIM = 1e5 + 5;
const int INF = 1e9 + 7;

int val[DIM], fth[DIM], lev[DIM], pos[DIM];

vector<int> edg[DIM], stk, aux, lst;
bitset<DIM> oki, mrk; vector<pair<int, int>> sol;

struct str
{
    int x, y;
    str(int _x = 0, int _y = 0) {
        x = _x;
        y = _y;
    }

    inline str operator +(const str &a) const {
        return str(x + a.x, y + a.y);
    }

    inline str operator -(const str &a) const {
        return str(x - a.x, y - a.y);
    }

    inline str operator +=(const str &a) {
        return *this = *this + a;
    }

    inline bool operator <(const str &a) const {
        if (x == a.x)
            return y < a.y;
        return x < a.x;
    }

    inline bool operator >(const str &a) const {
        if (x == a.x)
            return y > a.y;
        return x > a.x;
    }

    inline bool operator <=(const str &a) const {
        if (x == a.x)
            return y <= a.y;
        return x < a.x;
    }

    inline bool operator >=(const str &a) const {
        if (x == a.x)
            return y >= a.y;
        return x > a.x;
    }
} dp[DIM][2];

void dfs(int x, int f, pair<int, int> &ed)
{
    stk.push_back(x); fth[x] = f; bool ok = false;
    oki[x] = mrk[x] = true; lev[x] = lev[f] + 1;

    for (int y : edg[x]) {
        if (y == f) {
            if (ok)
                ed = make_pair(x, y);
            ok = true; continue;
        }

        if (!oki[y])
            dfs(y, x, ed);
        else
        if (lev[y] < lev[x]) {
            for (int z = x; z != fth[y]; z = fth[z])
                aux.push_back(z);
            ed = make_pair(x, y);
        }
    }

    stk.pop_back();
}

void calcdp(int x, int f, pair<int, int> ed, bool ok)
{
    if (ok)
        mrk[x] = false;
    if (ok and (x == ed.first or x == ed.second))
        return;

    vector<int> aux; vector<str> dpl, dpr;
    dp[x][0] = str(0, 0); dp[x][1] = str(-INF, -INF);

    for (int y : edg[x]) {
        if (y == f or (x == ed.first and y == ed.second)
                   or (y == ed.first and x == ed.second))
            continue;

        calcdp(y, x, ed, ok);
        if (!ok or (y != ed.first and y != ed.second))
            aux.push_back(y);
    }

    for (int y : aux)
        dp[x][0] += max(dp[y][0], dp[y][1]);

    dpl.resize(aux.size());
    for (int i = 0; i < aux.size(); ++i) {
        dpl[i] = max(dp[aux[i]][0], dp[aux[i]][1]);

        if (i - 1 >= 0)
            dpl[i] += dpl[i - 1];
    }

    dpr.resize(aux.size());
    for (int i = (int) aux.size() - 1; i >= 0; --i) {
        dpr[i] = max(dp[aux[i]][0], dp[aux[i]][1]);

        if (i + 1 < aux.size())
            dpr[i] += dpr[i + 1];
    }

    for (int i = 0; i < aux.size(); ++i) {
        str cns = str(1, val[x] != val[aux[i]]) + dp[aux[i]][0];

        if (i - 1 >= 0) cns += dpl[i - 1];
        if (i + 1 < aux.size()) cns += dpr[i + 1];

        if (dp[x][1] < cns)
            dp[x][1] = cns, pos[x] = aux[i];
    }
}

// 0 - blocked, 1 - must take, 2 - 0 or 1
void solvedp(int x, int f, pair<int, int> ed, bool ok, int msk)
{
    if (ok and (x == ed.first or x == ed.second))
        return;
    if (ok)
        mrk[x] = false;

    vector<int> aux;
    for (int y : edg[x]) {
        if (y == f or (x == ed.first and y == ed.second)
                   or (y == ed.first and x == ed.second))
            continue;

        if (!ok or (y != ed.first and y != ed.second))
            aux.push_back(y);
    }

    if (!msk or (msk == 2 and dp[x][0] >= dp[x][1])) {
        for (int y : aux)
            solvedp(y, x, ed, ok, 2);
    } else {
        sol.push_back(make_pair(x, pos[x]));
        for (int y : aux) if (y != pos[x])
            solvedp(y, x, ed, ok, 2);
        solvedp(pos[x], x, ed, ok, 0);
    }
}

int main(void)
{
    int n;
    cin >> n;

    for (int i = 1; i <= n; ++i) {
        int x;
        cin >> x >> val[i];

        edg[i].push_back(x);
        edg[x].push_back(i);
    }

    str ans;
    for (int i = 1; i <= n; ++i) {
        if (oki[i])
            continue;
        pair<int, int> ed;
        aux.clear(); lst.clear(); dfs(i, 0, ed);

        calcdp(ed.first, 0, ed, false);
        str vl1 = max(dp[ed.first][0], dp[ed.first][1]),
            vl2 = str(1, val[ed.first] != val[ed.second]);

        for (int x : edg[ed.first]) {
            if (!mrk[x] or x == ed.second)
                continue;

            lst.push_back(x);
            calcdp(x, 0, ed, true);
            vl2 += max(dp[x][0], dp[x][1]);
        }

        for (int x : edg[ed.second]) {
            if (!mrk[x] or x == ed.first)
                continue;

            lst.push_back(x);
            calcdp(x, 0, ed, true);
            vl2 += max(dp[x][0], dp[x][1]);
        }

        if (vl1 > vl2) {
            ans += vl1;
            solvedp(ed.first, 0, ed, false, 2);
        } else {
            ans += vl2;
            for (int x : lst)
                solvedp(x, 0, ed, true, 2);
            sol.push_back(ed);
        }
    }

    cout << ans.x << " " << ans.y << "\n";
    for (pair<int, int> pr : sol)
        cout << pr.first << " " << pr.second << "\n";

    return 0;
}


#include <bits/stdc++.h>
using namespace std;
const int N=5e3+5;
int n,m,k,x;
int sum[N],f[N][N];
//f[i][j]:前i个，用了j个
int main(){
	scanf("%d%d%d",&n,&m,&k);
	for (register int i=1; i<=n; ++i) scanf("%d",&x),sum[i]=sum[i-1]+x;
	for (register int i=m; i<=n; ++i)
	for (register int j=1; j<=min(i/m,k); ++j)
	{
		f[i][j]=f[i-m][j-1]+sum[i]-sum[i-m];
		f[i][j]=max(f[i][j],f[i-1][j]);
	}
	printf("%d\n",f[n][k]);
return 0;
}


#include <bits/stdc++.h>
using namespace std;

#define N 5005

int n,m,k,ans;
int f[N],sum[N],dp[N][N];

// dp[i][j]代表以i结尾、选j个的最优答案

int main()
{
	scanf("%d%d%d",&n,&m,&k);
	for(int i=1;i<=n;i++)
	{
		scanf("%d",&f[i]);
		sum[i]=sum[i-1]+f[i];
	}
	for(int i=m;i<=n;i++) dp[i][1]=sum[i]-sum[i-m];
	for(int j=2;j<=k;j++)
	for(int i=j*m;i<=n;i++)
	for(int p=(j-1)*m;p<=i-m;p++)
	dp[i][j]=max(dp[i][j],dp[i][1]+dp[p][j-1]);
	for(int i=k*m;i<=n;i++) ans=max(ans,dp[i][k]);
	printf("%d",ans);
	return 0;
}


#include<cstdio>
#define max(a,b) ((a)>(b)?(a):(b))
#define N 5005
using namespace std;
int n,m,k;
long long sum[N],f[N][N],maxn[N];
template<class T>inline void read(T &x) {
	register T s=0,g=0;char ch=getchar();
	while(ch<'0'||ch>'9'){if(ch=='-')g=1;ch=getchar();}
	while(ch>='0'&&ch<='9'){s=(s<<3)+(s<<1)+(ch^48);ch=getchar();}
	x=g?-s:s;
}
int main() {
	read(n),read(m),read(k);
	for(register int i=1,s;i<=n;i=-~i) {
		read(s);
		sum[i]=sum[i-1]+s;
		for(register int j=0;j<=k;j=-~j) {
			if(j*m>i) break;
			f[i][j]=max(f[i][j],maxn[j]);
			if(i>=m&&j) f[i][j]=max(f[i][j],f[i-m][j-1]+sum[i]-sum[i-m]);
			maxn[j]=max(maxn[j],f[i][j]);
		}
	}
	printf("%lld\n",f[n][k]);
	return 0;
}


#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
long long n,m,k,a[5005],s[5005],f[5005][5005];//注意用longlong
int main()
{
    scanf("%lld %lld %lld",&n,&m,&k);
    for(int i=1;i<=n;i++) scanf("%d",&a[i]);
    long long tot=0;
    for(int i=1;i<=n;i++)
    {
        tot+=a[i];
        if(i>=m)
        {
            s[i]=tot;
            tot-=a[i-m+1];
        }
    }
    for(int i=0;i<=n;i++) f[i][0]=0;//初值
    for(int i=m;i<=n;i++)
    {
        for(int j=1;j<=k;j++)
        {
            f[i][j]=f[i-1][j];
            f[i][j]=max(f[i][j],f[i-m][j-1]+s[i]);
            //状态转移方程，别忘记判断
        }
    }
    printf("%lld",f[n][k]);//输出
    return 0;
}


#include<bits/stdc++.h>
using namespace std;
long long n,m,k,dp[5010][5010],sum[10010],a;
int main()
{
	scanf("%lld%lld%lld",&n,&m,&k);
	for(int i=1;i<=n;i++)
	{
		scanf("%lld",&a);
		sum[i]=sum[i-1]+a;
	}
	for(int i=m;i<=n;i++)
		for(int j=1;j<=k;j++)
			dp[i][j]=max(dp[i-1][j],dp[i-m][j-1]+sum[i]-sum[i-m]);
	printf("%lld\n",dp[n][k]);
	return 0;
}


#include<bits/stdc++.h>
using namespace std;

long long n,m,k;
long long a[5005];
long long sum[5006],f[5005][5005];

int main() {
	scanf("%lld %lld %lld",&n,&m,&k);

	for(int i=1;i<=n;i++){
		scanf("%d",&a[i]);
	}
	long long qz=0;
	for(int i=1;i<=n;i++){

		qz+=a[i];
		if(i>=m){
			sum[i]=qz;
			qz-=a[i-m+1];
		}
	}
	memset(f,-1,sizeof(f));
	for(int i=0;i<=n;i++){
		f[i][0]=0;
	}
	for(int i=1;i<=n;i++){
        for(int j=1;j<=k;j++){
            f[i][j]=f[i-1][j];
            if(i>=m&&f[i-m][j-1]>-1){
            	f[i][j]=max(f[i][j],f[i-m][j-1]+sum[i]);
            }
        }
    }
    printf("%lld",f[n][k]);
	return 0;
}


#include <cstdio>
#include <queue>
using namespace std;
queue <int> q[5005];
int a[5005],sum[5005],f[5005];
int n,len,m;
int main()
{
	scanf("%d%d%d",&n,&len,&m);
	for(int i=1;i<=n;++i)
		scanf("%d",&a[i]),sum[i]=sum[i-1]+a[i];
	for(int i=len;i<=n;++i)
	{
//		printf("\ni=%d\n",i);
		for(int j=1;j<i/len&&j<=m;++j)
		{
//			printf("j=%d\n",j);
			f[j]=max(f[j],q[j].front());
			q[j].pop();
		}
		for(int j=1;j<=i/len&&j<=m;++j)
		{
			int dq=f[j-1]+sum[i]-sum[i-len];
			q[j].push(dq);
//			puts("nalanala");
		}
	}
	while(!q[m].empty()) f[m]=max(f[m],q[m].front()),q[m].pop();
	printf("%d",f[m]);
	return 0;
}


#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
struct node
{
	long long a,sum,id;
}t[5100];
long long cmp(node x,node y)
{
	return x.sum>y.sum;
}
long long m,n,k,ans,head=9999,tail;
long long dp[5003][5003];
int main()
{
	cin>>n>>m>>k;
	for(int i=1;i<=n;i++)
	{
		cin>>t[i].a;
		t[i].id=i;
		t[i].sum=t[i].a+t[i-1].sum;
		if(i>m)
		t[i].sum=t[i].sum-t[i-m].a;
	}
	dp[m][1]=t[m].sum;
//	sort(t+1,t+n+1,cmp);
//	for(int i=1;i<=n;i++)
//	{
//		cout<<t[i].sum<<' ';
//	}
//	for(int i=1;i<=k;i++)
//	{
//		if(head>t[i].id+m)
//		ans+=t[i].sum,head=t[i].id;
//		else
//		if(tail<t[i].id)
//		ans+=t[i].sum,tail=t[i].id+m;
//	}
	for(int i=m;i<=n;i++)
	{
		for(int j=1;j<=k;j++)
		{									//dp[i][j]表示i个数之前有j个区间的最大值 ***
			dp[i][j]=max(dp[i-1][j],dp[i-m][j-1]+t[i].sum);
		}
	}
	cout<<dp[n][k];
//	return 0;
//	for(i=1;i<=n;i++)
//	{
//
//	}
//	for(int i=1;i<=n;i++)
//	{
//		for(int j=1;j<=i;j++)
//		{
//			dp[j][i]=dp[j-1][i]+a[j];
//		}
//	}
	return 0;
}


#include <iostream>
#include <bits/stdc++.h>
using namespace std;

int main()
{
long long int n,m,k,t,mr;
cin>>n>>m>>k;
mr=m-1;
long long int a[n];
for (int i=0;i<n;i++){
    cin>>a[i];
}
t=n-m+1;
long long int dp[t];
dp[0]=0;
for (int i=0;i<m;i++){
    dp[0]+=a[i];
}
for (int i=1;i<n-m+1;i++){
    dp[i]=dp[i-1]-a[i-1]+a[i+m-1];
}
sort(dp,dp+t);
long long int s=0;
for (int i=0;i<k;i++){
    s+=dp[t-i-1];
}
cout<<s;
    return 0;
}


#include <iostream>
#include <bits/stdc++.h>
using namespace std;
#define ll long long
ll dp[100][100];
ll n,m,k;
ll f (ll i,ll j,ll a[]){
    if (dp[n][k]!=-1){
        return dp[n][k];
    }
 if (i<=j*m){
    return a[i];
}
 if (i<m){
    return 0;
}
if (j==0){
    return 0;
}
else {
    dp[i][j]=max(f(i-1,j,a),a[i]-a[i-m]+f(i-m,j-1,a));
}
}

int main()
{
cin>>n>>m>>k;
ll l=0;
ll s[n+1],a[n+1];
for (int i=1;i<=n;i++){
    cin>>s[i];
    l+=s[i];
    a[i]=l;
}
memset(dp,-1,sizeof dp);

cout<<f(n,k,a);
    return 0;
}


#include <iostream>

using namespace std;

int main()
{
long long int n,m,k,s=0;
cin>>n>>m>>k;
long long int a[n],sum[n];
for (int i=0;i<n;i++){
    cin>>a[i];
    s+=a[i];
    sum[i]=s;
}

long long int dp[k+1][n];
for (int i=0;i<n;i++){
    dp[0][i]=0;
}
for (int i=1;i<k+1;i++){
    for (int j=0;j<n;j++){
        if(i*m>j+1){
            dp[i][j]=0;
        }
        else if (i*m==j+1){
            dp[i][j]=sum[j];
        }
        else {
            dp[i][j]=max(dp[i][j-1],dp[i-1][j-m]+sum[j]-sum[j-m]);
        }
    }
}
cout<<dp[k][n-1];
    return 0;
}


#include <iostream>
#include <bits/stdc++.h>
using namespace std;

int main()
{
long long int n,m,k,l=0;
cin>>n>>m>>k;
long long int a[n+1],s[n+1];
long long int dp[n+1][k+1];
memset(dp,0,sizeof dp);
for (int i=1;i<=n;i++){
    s[i]=0;
}
for (int i=1;i<n+1;i++){
    cin>>a[i];
    l+=a[i];
    s[i]=l;
}

for (int i=1;i<=n;i++){
    for (int j=1;j<=k;j++){
    if (i<=j*m){
        dp[i][j]=s[i];
    }
    else {
        dp[i][j]=max(dp[i-1][j],s[i]-s[i-m]+dp[i-m][j-1]);
    }

}}
cout<<dp[n][k];

    return 0;
}


#include <iostream>
#include <bits/stdc++.h>

using namespace std;
#define ll long long
ll a[5200];
ll n,m,k;
 ll res[5200][5200];
ll dp(int index,int kk){
if (index>n-m){
    return 0;
}
if (kk==0){
    return 0;
}
if(res[index][kk]!=-1){
    return res[index][kk];
}
else {
    return res[index][kk]=max(a[index]+dp(index+m,kk-1),dp(index+1,kk));
}

}
int main()
{

cin>>n>>m>>k;
for (int i=0;i<n;i++){
    cin>>a[i];
}
for (int i=0;i<=n-m;i++){
    for (int j=1;j<m;j++){
        a[i]+=a[i+j];
    }
}
memset(res,-1,sizeof res);
cout<<dp(0,k);

    return 0;
}


#include <iostream>
#include <bits/stdc++.h>
using namespace std;

int main()
{
long long int n,m,k,t,mr;
cin>>n>>m>>k;
mr=m-1;
long long int a[n];
for (int i=0;i<n;i++){
    cin>>a[i];
}
t=n-m+1;
long long int dp[t];
dp[0]=0;
for (int i=0;i<m;i++){
    dp[0]+=a[i];
}
for (int i=1;i<n-m+1;i++){
    dp[i]=dp[i-1]-a[i-1]+a[i+m-1];
}
sort(dp,dp+t);
     long long int s=0;
for (int i=0;i<k;i++){
s+=dp[t-i-1];
}
cout<<s;
    return 0;
}


#include <iostream>
#include <bits/stdc++.h>
using namespace std;

int main()
{
long long int n,m,k,t,mr;
cin>>n>>m>>k;
mr=m-1;
long long int a[n];
for (int i=0;i<n;i++){
    cin>>a[i];
}
t=n-m;
long long int dp[t];
dp[0]=0;
for (int i=0;i<m;i++){
    dp[0]+=a[i];
}
for (int i=1;i<n-m;i++){
    dp[i]=dp[i-1]-a[i-1]+a[i+m];
}
sort(dp,dp+t);
long long int s=0;
for (int i=0;i<k;i++){
    s+=dp[t-i-1];
}
cout<<s;
    return 0;
}


#include <bits/stdc++.h>

using namespace std;

//#define int long long
//#define INT_MAX (1 << 40)

typedef pair<int, int> ii;
#define fr first
#define sc second
#define pb push_back
#define mp make_pair
#define max(a, b) (a > b ? a : b)
#define min(a, b) (a < b ? a : b)
#define sqr(n) n*n
#define all(x) x.begin(),x.end()
#define scan(n) scanf("%d", &n)

typedef long long ll;

ll dp[5010][5010] = { 0 };

int main()
{
    int n, m, k;
    cin >> n >> m >> k;
    vector<ll> arr(n + 1);
    for (int i = 1; i <= n; i++)
        cin >> arr[i], arr[i] += arr[i - 1];
    for (int i = 1; i <= k; i++)
        for (int j = m; j <= n; j++)
            dp[i][j] = max(dp[i][j - 1], dp[i - 1][j - m] + arr[j] - arr[j - m]);
    cout << dp[k][n] << endl;
}


#include <bits/stdc++.h>

using namespace std;

//#define int long long
//#define INT_MAX (1 << 40)

typedef pair<int, int> ii;
#define fr first
#define sc second
#define pb push_back
#define mp make_pair
#define max(a, b) (a > b ? a : b)
#define min(a, b) (a < b ? a : b)
#define sqr(n) n*n
#define all(x) x.begin(),x.end()
#define scan(n) scanf("%d", &n)

typedef long long ll;

int main()
{
    int n, m, k;
    cin >> n >> m >> k;
    vector<int> arr(n);
    for (int i = 0; i < n; i++)
        cin >> arr[i];
    int ans = 0;
    while (k--)
    {
        deque<ii> cur;
        long long mxsum = -1;
        deque<ii> mx;
        long long sum = 0;
        for (int i = 0; i < n; i++)
        {
            if (arr[i] == -1)
                continue;
            sum += arr[i];
            cur.push_back(mp(arr[i], i));
            if (cur.size() < m)
                continue;
            if (cur.size() > m)
                sum -= cur.front().fr, cur.pop_front();
            if (sum > mxsum)
                mxsum = sum, mx = cur;
        }
        ans += mxsum;
        while (!mx.empty())
            arr[mx.front().sc] = -1, mx.pop_front();
    }
    cout << ans << endl;
}


#include <bits/stdc++.h>

using namespace std;

//#define int long long
//#define INT_MAX (1 << 40)

typedef pair<int, int> ii;
#define fr first
#define sc second
#define pb push_back
#define mp make_pair
#define max(a, b) (a > b ? a : b)
#define min(a, b) (a < b ? a : b)
#define sqr(n) n*n
#define all(x) x.begin(),x.end()
#define scan(n) scanf("%d", &n)

typedef long long ll;

int n, m, k;
vector<int> arr;
ll memo[5010][5010];

ll bt(int b, int cnt)
{
    if (memo[b][cnt] != -1)
        return memo[b][cnt];
    if (cnt == k)
        return 0;
    ll ret = 0;
    ll sum = 0;
    deque<int> cur;
    for (int i = b; i < n; i++)
    {
        sum += arr[i];
        cur.push_back(arr[i]);
        if (cur.size() < m)
            continue;
        if (cur.size() > m)
            sum -= cur.front(), cur.pop_front();
        ret = max(ret, sum + bt(i + 1, cnt + 1));
    }
    return memo[b][cnt] = ret;
}

int main()
{
    get(n), get(m), get(k);
    arr = vector<int>(n);
    for (int i = 0; i < n; i++)
        get(arr[i]);
    memset(memo, -1, sizeof memo);
    printf("%I64d\n", bt(0, 0));
}


#include <bits/stdc++.h>

using namespace std;

//#define int long long
//#define INT_MAX (1 << 40)

typedef pair<int, int> ii;
#define fr first
#define sc second
#define pb push_back
#define mp make_pair
#define max(a, b) (a > b ? a : b)
#define min(a, b) (a < b ? a : b)
#define sqr(n) n*n
#define all(x) x.begin(),x.end()
#define scan(n) scanf("%d", &n)

typedef long long ll;

int n, m, k;
vector<int> arr;
ll memo[5010][5010];

inline ll bt(int b, int cnt)
{
    int x = k - cnt;
    int l = n - b;
    if (x * m > l)
        return 0;
    if (memo[b][cnt] != -1)
        return memo[b][cnt];
    if (cnt == k)
        return 0;
    ll ret = 0;
    ll sum = 0;
    deque<int> cur;
    for (int i = b; i < n - (x - 1) * m; i++)
    {
        sum += arr[i];
        cur.push_back(arr[i]);
        if (cur.size() < m)
            continue;
        if (cur.size() > m)
            sum -= cur.front(), cur.pop_front();
        ret = max(ret, sum + bt(i + 1, cnt + 1));
    }
    return memo[b][cnt] = ret;
}

int main()
{
    scan(n); scan(m); scan(k);
    arr = vector<int>(n);
    for (int i = 0; i < n; i++)
        scan(arr[i]);
    memset(memo, -1, sizeof memo);
    printf("%I64d\n", bt(0, 0));
}


#include <bits/stdc++.h>

using namespace std;

//#define int long long
//#define INT_MAX (1 << 40)

typedef pair<int, int> ii;
#define fr first
#define sc second
#define pb push_back
#define mp make_pair
#define max(a, b) (a > b ? a : b)
#define min(a, b) (a < b ? a : b)
#define sqr(n) n*n
#define all(x) x.begin(),x.end()
#define scan(n) scanf("%d", &n)

typedef long long ll;

ll dp[5010][5010] = { 0 };

int main()
{
    int n, m, k;
    cin >> n >> m >> k;
    vector<int> arr(n + 1);
    for (int i = 1; i <= n; i++)
        cin >> arr[i], arr[i] += arr[i - 1];
    for (int i = 1; i <= k; i++)
        for (int j = m; j <= n; j++)
            dp[i][j] = max(dp[i][j - 1], dp[i - 1][j - m] + arr[j] - arr[j - m]);
    cout << dp[k][n] << endl;
}


#include <bits/stdc++.h>

using namespace std;

//#define int long long
//#define INT_MAX (1 << 40)

typedef pair<int, int> ii;
#define fr first
#define sc second
#define pb push_back
#define mp make_pair
#define max(a, b) (a > b ? a : b)
#define min(a, b) (a < b ? a : b)
#define sqr(n) n*n
#define all(x) x.begin(),x.end()
#define scan(n) scanf("%d", &n)

typedef long long ll;

int n, m, k;
vector<int> arr;
ll memo[5010][5010];

int bt(int b, int cnt)
{
    if (memo[b][cnt] != -1)
        return memo[b][cnt];
    if (cnt == k)
        return 0;
    if (n - b < (k - cnt) * m)
        return INT_MIN;
    ll ret = 0;
    ll sum = 0;
    deque<int> cur;
    for (int i = b; i < n; i++)
    {
        sum += arr[i];
        cur.push_back(arr[i]);
        if (cur.size() < m)
            continue;
        if (cur.size() > m)
            sum -= cur.front(), cur.pop_front();
        ret = max(ret, sum + bt(i + 1, cnt + 1));
    }
    return memo[b][cnt] = ret;
}

int main()
{
    cin >> n >> m >> k;
    arr = vector<int>(n);
    for (int i = 0; i < n; i++)
        cin >> arr[i];
    memset(memo, -1, sizeof memo);
    cout << bt(0, 0) << endl;
}


#include <bits/stdc++.h>

using namespace std;

//#define int long long
//#define INT_MAX (1 << 40)

typedef pair<int, int> ii;
#define fr first
#define sc second
#define pb push_back
#define mp make_pair
#define max(a, b) (a > b ? a : b)
#define min(a, b) (a < b ? a : b)
#define sqr(n) n*n
#define all(x) x.begin(),x.end()
#define scan(n) scanf("%d", &n)

typedef long long ll;

ll dp[5010][5010] = { 0 };

int main()
{
    int n, m, k;
    cin >> n >> m >> k;
    vector<int> arr(n + 1);
    for (int i = 1; i <= n; i++)
        cin >> arr[i], arr[i] += arr[i - 1];
    for (int i = 1; i <= k; i++)
        for (int j = 1; j <= n; j++)
            dp[i][j] = max(dp[i][j - 1], dp[i - 1][j - m] + arr[j] - arr[j - m]);
    cout << dp[k][n] << endl;
}


#define _CRT_SECURE_NO_WARNINGS

#include <cstdio>
#include <cstring>
#include <cassert>
#include <climits>
#include <iostream>
#include <iomanip>
#include <algorithm>
#include <set>
#include <vector>
#include <deque>
#include <queue>
#include <stack>
#include <utility>
#include <string>
#include <bitset>
#include <map>

using namespace std;

typedef long long ll;
typedef pair<int, int> ii;
#define fr first
#define sc second
#define mp make_pair
#define pb push_back

const int MAXN = 5010;

int n, m, k;
int ar[MAXN];
ll sum[MAXN];

ll dp[MAXN][MAXN];

int main()
{
	scanf("%d%d%d", &n, &m, &k);
	for (int i = 1; i <= n; i++)
	{
		scanf("%d", ar + i);
		sum[i] = ar[i] + sum[i - 1];
	}
	for (int i = m; i <= n; i++)
	{
		for (int j = 1; j <= k; j++)
		{
			dp[i][j] = max(dp[i - m][j - 1] + sum[i] - sum[i - m], dp[i - 1][j]);
		}
	}
	printf("%I64d\n", dp[n][k]);
}


#include <bits/stdc++.h>

using namespace std;

//#define int long long
//#define INT_MAX (1 << 40)

typedef pair<int, int> ii;
#define fr first
#define sc second
#define pb push_back
#define mp make_pair
#define max(a, b) (a > b ? a : b)
#define min(a, b) (a < b ? a : b)
#define sqr(n) n*n
#define all(x) x.begin(),x.end()
#define scan(n) scanf("%d", &n)

typedef long long ll;

int n, m, k;
vector<int> arr;
ll memo[5010][5010];

inline ll bt(int b, int cnt)
{
    int x = k - cnt;
    int l = n - b;
    if (x * m > l)
        return 0;
    if (memo[b][cnt] != -1)
        return memo[b][cnt];
    if (cnt == k)
        return 0;
    ll ret = 0;
    ll sum = 0;
    deque<int> cur;
    for (int i = b; i < n; i++)
    {
        sum += arr[i];
        cur.push_back(arr[i]);
        if (cur.size() < m)
            continue;
        if (cur.size() > m)
            sum -= cur.front(), cur.pop_front();
        ret = max(ret, sum + bt(i + 1, cnt + 1));
    }
    return memo[b][cnt] = ret;
}

int main()
{
    scan(n); scan(m); scan(k);
    arr = vector<int>(n);
    for (int i = 0; i < n; i++)
        scan(arr[i]);
    memset(memo, -1, sizeof memo);
    printf("%I64d\n", bt(0, 0));
}


#include <bits/stdc++.h>

using namespace std;

//#define int long long
//#define INT_MAX (1 << 40)

typedef pair<int, int> ii;
#define fr first
#define sc second
#define pb push_back
#define mp make_pair
#define max(a, b) (a > b ? a : b)
#define min(a, b) (a < b ? a : b)
#define sqr(n) n*n
#define all(x) x.begin(),x.end()
#define scan(n) scanf("%d", &n)

typedef long long ll;

int main()
{
    int n, m, k;
    cin >> n >> m >> k;
    vector<int> arr(n);
    for (int i = 0; i < n; i++)
        cin >> arr[i];
    int ans = 0;
    while (k--)
    {
        deque<ii> cur;
        long long mxsum = -1;
        deque<ii> mx;
        long long sum = 0;
        for (int i = 0; i < n; i++)
        {
            if (arr[i] == -1)
            {
                cur = deque<ii>();
                sum = 0;
                continue;
            }
            sum += arr[i];
            cur.push_back(mp(arr[i], i));
            if (cur.size() < m)
                continue;
            if (cur.size() > m)
                sum -= cur.front().fr, cur.pop_front();
            if (sum > mxsum)
                mxsum = sum, mx = cur;
        }
        ans += mxsum;
        while (!mx.empty())
            arr[mx.front().sc] = -1, mx.pop_front();
    }
    cout << ans << endl;
}


#include <bits/stdc++.h>

using namespace std;

//#define int long long
//#define INT_MAX (1 << 40)

typedef pair<int, int> ii;
#define fr first
#define sc second
#define pb push_back
#define mp make_pair
#define max(a, b) (a > b ? a : b)
#define min(a, b) (a < b ? a : b)
#define sqr(n) n*n
#define all(x) x.begin(),x.end()
#define scan(n) scanf("%d", &n)

typedef long long ll;

int n, m, k;
vector<int> arr;
ll memo[5010][5010];

ll bt(int b, int cnt)
{
    if (memo[b][cnt] != -1)
        return memo[b][cnt];
    if (cnt == k)
        return 0;
    ll ret = 0;
    ll sum = 0;
    deque<int> cur;
    for (int i = b; i < n; i++)
    {
        sum += arr[i];
        cur.push_back(arr[i]);
        if (cur.size() < m)
            continue;
        if (cur.size() > m)
            sum -= cur.front(), cur.pop_front();
        ret = max(ret, sum + bt(i + 1, cnt + 1));
    }
    return memo[b][cnt] = ret;
}

int main()
{
    scan(n); scan(m); scan(k);
    arr = vector<int>(n);
    for (int i = 0; i < n; i++)
        scan(arr[i]);
    memset(memo, -1, sizeof memo);
    printf("%I64d\n", bt(0, 0));
}


#include <bits/stdc++.h>

using namespace std;

//#define int long long
//#define INT_MAX (1 << 40)

typedef pair<int, int> ii;
#define fr first
#define sc second
#define pb push_back
#define mp make_pair
#define max(a, b) (a > b ? a : b)
#define min(a, b) (a < b ? a : b)
#define sqr(n) n*n
#define all(x) x.begin(),x.end()
#define scan(n) scanf("%d", &n)

typedef long long ll;

int n, m, k;
vector<int> arr;
ll memo[5010][5010];

inline ll bt(int b, int cnt)
{
    int x = k - cnt;
    int l = n - b;
    if (x * m > l)
        return 0;
    if (memo[b][cnt] != -1)
        return memo[b][cnt];
    if (cnt == k)
        return 0;
    ll ret = 0;
    ll sum = 0;
    deque<int> cur;
    for (int i = b; i < n - x * m + 1; i++)
    {
        sum += arr[i];
        cur.push_back(arr[i]);
        if (cur.size() < m)
            continue;
        if (cur.size() > m)
            sum -= cur.front(), cur.pop_front();
        ret = max(ret, sum + bt(i + 1, cnt + 1));
    }
    return memo[b][cnt] = ret;
}

int main()
{
    scan(n); scan(m); scan(k);
    arr = vector<int>(n);
    for (int i = 0; i < n; i++)
        scan(arr[i]);
    memset(memo, -1, sizeof memo);
    printf("%I64d\n", bt(0, 0));
}


#include <bits/stdc++.h>

using namespace std;

//#define int long long
//#define INT_MAX (1 << 40)

typedef pair<int, int> ii;
#define fr first
#define sc second
#define pb push_back
#define mp make_pair
#define max(a, b) (a > b ? a : b)
#define min(a, b) (a < b ? a : b)
#define sqr(n) n*n
#define all(x) x.begin(),x.end()
#define scan(n) scanf("%d", &n)

typedef long long ll;

int main()
{
    int n, m, k;
    cin >> n >> m >> k;
    vector<int> arr(n);
    for (int i = 0; i < n; i++)
        cin >> arr[i];
    int ans = 0;
    while (k--)
    {
        deque<ii> cur;
        ll mxsum = -1;
        deque<ii> mx;
        ll sum = 0;
        int del = 0;
        for (int i = 0, cnt = 0; i < n - k * m; i++)
        {
            if (arr[i] == -1)
            {
                cur = deque<ii>();
                sum = 0;
                cnt++;
                continue;
            }
            sum += arr[i];
            cur.push_back(mp(arr[i], i));
            if (cur.size() < m)
                continue;
            if (cur.size() > m)
                sum -= cur.front().fr, cur.pop_front();
            if (sum > mxsum)
                mxsum = sum, mx = cur;
        }
        ans += mxsum;
        while (!mx.empty())
            arr[mx.front().sc] = -1, mx.pop_front(), del++;
    }
    cout << ans << endl;
}


#include <bits/stdc++.h>
#define ll long long
#define ld long double
#define pb push_back
#define read(x) scanf( "%lld" , &x )
#define forq(i , a , b) for (int i = (a); i <= (b); ++i)
#define forr(i , b) forq( i , 0 , b - 1 )
#define carr( n , array ) forr(i , n) read(array[i])
#define coutarr(n , array ) cout << "\n" ; forr (i , n) printf("%lld " , array[i]) ; cout << "\n" ;
#define F first
#define S second
#define IF ->first
#define IS ->second
#define qqmemset(array , val) memset (array , val , sizeof(array))
#define ALLV(vect) vect.begin() , vect.end()
#define sizee(vec) (ll)vec.size()

ll R = 7 + 1e9 , NUMTESTCASE ;
const int NN = 10 + 5e3 ;
const double pi = acos(-1.0) ;
int di [4] = {1 , 0 , -1 , 0} , dj [4] = {0 , 1 , 0 , -1} , DI [8] = {1 , 1 , 0 , -1 , -1 , -1 , 0 , 1} , DJ [8] = {0 , 1 , 1 , 1 , 0 , -1 , -1 , -1} ;
using namespace std;
ll dp1[NN] , a[NN] , n , m , k , ans , memo[NN][NN] ;
ll dp(int x , int num) {
    if (num < 0) return - 1e18 ;
    //if ( n - x + 1 < (k - num + 1) * m ) return -1e18 ;
    if (memo[x][num]) return memo[x][num] ;
    if (num == 1) return dp1[x] ;
    ll flag = 0 ;
    forq (i , x + m , n)
        flag = max(flag , dp (i , num - 1) ) ;
    memo[x][num] = flag + dp1[x] ;
    return memo[x][num] ;
}
int main()
{
    cin >> n >> m >> k ;
    forq (i , 1 , n) scanf("%lld" , &a[i]) ;
    if (m * k == n) {
        ll res = 0 ;
        forq (i , 1 , n) res += a[i] ;
        return cout << res , 0 ;
    }
    forq (i , n - m + 1, n) dp1[n - m + 1] += a[i] ;
    for (int i = n - m ; i >= 1 ; i --)
        dp1[i] = dp1[i + 1] + a[i] - a[i + m] ;
    for (int i = n ; i >= 1 ; i --) forq (j , 1 , k) dp(i , j) ;
    forq (i , 1, n) ans = max(ans , dp(i , k)) ;
    cout << ans ;
    return 0;
}


#include <bits/stdc++.h>
#define ll long long
#define ld long double
#define pb push_back
#define read(x) scanf( "%lld" , &x )
#define forq(i , a , b) for (int i = (a); i <= (b); ++i)
#define forr(i , b) forq( i , 0 , b - 1 )
#define carr( n , array ) forr(i , n) read(array[i])
#define coutarr(n , array ) cout << "\n" ; forr (i , n) printf("%lld " , array[i]) ; cout << "\n" ;
#define F first
#define S second
#define IF ->first
#define IS ->second
#define qqmemset(array , val) memset (array , val , sizeof(array))
#define ALLV(vect) vect.begin() , vect.end()
#define sizee(vec) (ll)vec.size()

ll R = 7 + 1e9 , NUMTESTCASE ;
const int NN = 10 + 5e3 ;
const double pi = acos(-1.0) ;
int di [4] = {1 , 0 , -1 , 0} , dj [4] = {0 , 1 , 0 , -1} , DI [8] = {1 , 1 , 0 , -1 , -1 , -1 , 0 , 1} , DJ [8] = {0 , 1 , 1 , 1 , 0 , -1 , -1 , -1} ;
using namespace std;
ll dp1[NN] , a[NN] , n , m , k , ans , memo[NN][NN] ;
bool visited [NN][NN] ;
ll dp(int x , int num) {
    //if ( n - x - m + 1 <= (num - 1) * m ) return 0 ;
    if (visited[x][num]) return memo[x][num] ;
    visited[x][num] = true ;
    //cout << x << " " << num << endl ;
    ll flag = 0 ;
    forq (i , x + m , n)
        flag = max(flag , dp (i , num - 1) ) ;
    memo[x][num] = flag + dp1[x] ;
    return memo[x][num] ;
}
int main()
{
    cin >> n >> m >> k ;
    forq (i , 1 , n) scanf("%lld" , &a[i]) ;
    forq (i , n - m + 1, n) dp1[n - m + 1] += a[i] ;
    memo[n - m + 1][1] = dp1[n - m + 1] ;
    for (int i = n - m ; i >= 1 ; i --)
        dp1[i] = memo[i][1] = dp1[i + 1] + a[i] - a[i + m] ;
    forq (i , 1 , n) visited[i][1] = true ;
    forq (j , 1 , k)
        for (int i = n - m * j + 2 ; i <= n ; i ++)
            visited[i][j] = true ;
    forq (i , 1, n) ans = max(ans , dp(i , k)) ;
    cout << ans ;
    return 0;
}


#include <bits/stdc++.h>
#define ll long long
#define ld long double
#define pb push_back
#define read(x) scanf( "%lld" , &x )
#define forq(i , a , b) for (int i = (a); i <= (b); ++i)
#define forr(i , b) forq( i , 0 , b - 1 )
#define carr( n , array ) forr(i , n) read(array[i])
#define coutarr(n , array ) cout << "\n" ; forr (i , n) printf("%lld " , array[i]) ; cout << "\n" ;
#define F first
#define S second
#define IF ->first
#define IS ->second
#define qqmemset(array , val) memset (array , val , sizeof(array))
#define ALLV(vect) vect.begin() , vect.end()
#define sizee(vec) (ll)vec.size()

ll R = 7 + 1e9 , NUMTESTCASE ;
const int NN = 10 + 5e3 ;
const double pi = acos(-1.0) ;
int di [4] = {1 , 0 , -1 , 0} , dj [4] = {0 , 1 , 0 , -1} , DI [8] = {1 , 1 , 0 , -1 , -1 , -1 , 0 , 1} , DJ [8] = {0 , 1 , 1 , 1 , 0 , -1 , -1 , -1} ;
using namespace std;
ll dp1[NN] , a[NN] , n , m , k , ans ;
void solve (int x , int num , ll sum) {
    if (num == k) ans = max(ans , sum) ;
    else forq (i , x + m , n)
        solve(i , num + 1 , sum + dp1[i]) ;
}
int main()
{
    cin >> n >> m >> k ;
    forq (i , 1 , n) scanf("%lld" , &a[i]) ;
    forq (i , n - m + 1, n) dp1[n - m + 1] += a[i] ;
    for (int i = n - m ; i >= 1 ; i --)
        dp1[i] = dp1[i + 1] + a[i] - a[i + m] ;
    forq (i , 1 , n) solve(i , 1 , dp1[i]) ;
    cout << ans ;
    return 0;
}