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

struct Point {
    long long x, y;
};

bool ccw(Point a, Point b) {
    if (!a.y && !b.y) return a.x < b.x;
    return a.x * b.y < a.y * b.x;
}

bool cmp(Point p1, Point p2) {
    if ((p1.y >= 0 && p2.y >= 0) || (p1.y < 0 && p2.y < 0)) {
        return ccw(p1, p2);
    }
    return p1.y > p2.y;
}

long long cross(const Point& A, const Point& B) {
    return A.x * B.y - A.y * B.x;
}

// cross(CA, CB) < 0: CA -> turns right -> CB
long long cross(const Point&A, const Point& B, const Point& C) {
    Point D = {A.x - C.x, A.y - C.y};
    Point E = {B.x - C.x, B.y - C.y};
    return cross(D, E);
}

bool intersect(Point a, Point b, Point c, Point d) {
    return cross(b, c, a) * cross(b, d, a) < 0 and
        cross(d, a, c) * cross(d, b, c) < 0;
}

int a[2005], vs[2005], cycleInd[2005], merged[2005];
vector<int> cycle[2005];
Point pts[2005];

void dfs(int u, int c) {
    if (vs[u]) return;
    vs[u] = 1;
    cycle[c].push_back(u);
    cycleInd[u] = c;

    dfs(a[u], c);
}
    
vector<pair<int, int>> operations;
void doSwap(int i, int j) {
    swap(a[i], a[j]);
    operations.push_back({i, j});
    // cout << i << " " << j << endl;
    //GD_SEGMENT(pts[i].x, pts[i].y, pts[j].x, pts[j].y);
}

int main() {
    //GD_INIT("output.html");
    // freopen("input.txt", "r", stdin);
    int n;
    cin >> n;
    int center = 0;
    for (int i = 1; i <= n; i++) {
        cin >> pts[i].x >> pts[i].y >> a[i];
        //GD_POINT(pts[i].x, pts[i].y);
        //GD_PAUSE();
    }

    int numCycles = 0;
    for (int i = 1; i <= n; i++) {
        if (vs[i] || a[i] == i) continue;
        dfs(i, ++numCycles);
    }
    if (numCycles == 0) {
        cout << 0;
        return 0;
    }
    
    center = cycle[1][0];
    //GD_POINT(pts[center].x, pts[center].y, "red");

    vector<int> index;
    for (int i = 1; i <= numCycles; i++) {
        for (auto j: cycle[i]) {
            // cout << j << " ";
            if (j != center) index.push_back(j);
        }
        // cout << endl;
    }

    sort(index.begin(), index.end(), [&](int i, int j) {
        Point A = {pts[i].x - pts[center].x, pts[i].y - pts[center].y};
        Point B = {pts[j].x - pts[center].x, pts[j].y - pts[center].y};
        return cmp(A, B);
    });

    int turnPoint = -1;
    for (int i = 0; i + 1 < index.size(); i++) {
        if (cross(pts[index[i]], pts[index[i + 1]], pts[center]) > 0) {
            turnPoint = i;
        }
    }
    if (turnPoint != -1) {
        rotate(index.begin(), index.begin() + turnPoint + 1, index.end());
    }
    // cout << endl;

    int start = cycle[1][1];
    merged[1] = 1;

    int pos;
    for (int i = 0; i < index.size(); i++) {
        //GD_POINT(pts[index[i]].x, pts[index[i]].y, "blue");
        if (start == index[i]) pos = i;
    }

    for (int i = pos - 1; i >= 0; i--) {
        if (!merged[cycleInd[index[i]]]) {
            doSwap(index[i], index[i + 1]);
            merged[cycleInd[index[i]]] = 1;
        }
    }

    for (int i = pos + 1; i < index.size(); i++) {
        if (!merged[cycleInd[index[i]]]) {
            doSwap(index[i], index[i - 1]);
            merged[cycleInd[index[i]]] = 1;
        }
    }
    // for (int i = 1; i <= n; i++) {
    //     cout << a[i] << " ";
    // }
    // cout << endl;

    while (a[center] != center) {
        doSwap(center, a[center]);
    }
    cout << operations.size() << '\n';
    for (auto i: operations) cout << i.first << " " << i.second << "\n";

    // for (int i = 0; i < operations.size(); i++) {
    //     for (int j = i + 1; j < operations.size(); j++) {
    //         Point a = pts[operations[i].first];
    //         Point b = pts[operations[i].second];
    //         Point c = pts[operations[j].first];
    //         Point d = pts[operations[j].second];
    //         if (intersect(a, b, c, d)) {
    //             cout << i << " " << j << " BAD" << endl;
    //         }
    //     }
    // }
    return 0;
}