#include <bits/stdc++.h>
using namespace std;
#pragma GCC optimize("unroll-loops")
#pragma GCC optimize("avx2")
template<typename T>
istream& operator>>(istream& stream, vector<T>& a) {
    for (auto& x : a) stream >> x;
    return stream;
}
template<typename T>
ostream& operator<<(ostream& stream, vector<T>& a) {
    for (auto& x : a) stream << x << ' ';
    cout << '\n';
    return stream;
}
template<typename T1, typename T2>
istream& operator>>(istream& stream, vector<pair<T1, T2>>& a) {
    for (auto& [x, y] : a) stream >> x >>  y;
    return stream;
}
template<typename T1, typename T2>
ostream& operator<<(ostream& stream, vector<pair<T1, T2>>& a) {
    for (auto& [x, y] : a) stream << x << ' ' << y << '\n';
    return stream;
}
template<typename T1, typename T2>
inline void amax(T1& a, T2 b) {
    a = max(a, b);
}
template<typename T1, typename T2>
inline void amin(T1& a, T2 b) {
    a = min(a, b);
}

//#define int int64_t
#define all(x) x.begin(), x.end()
#define pb emplace_back
#define ff first
#define ss second
#define sz(x) (int)(x.size())
#define deb cout << "----------------------" << endl
#define MIN(x) *min_element(all(x))
#define MINID(x) min_element(all(x)) - x.begin()
#define MAX(x) *max_element(all(x))
#define MAXID(x) max_element(all(x)) - x.begin()
#define push emplace
#define SUM(x) accumulate(all(x), 0ll)
#define sj(x) sort(all(x)), x.erase(unique(all(x)), x.end())

mt19937 rnd(221);

using ll = long long;
using vi = vector<int>;
using pi = pair<int,int>;
using vvi = vector<vi>;
using vpi = vector<pi>;
using vvpi = vector<vpi>;
using ld = long double;

const int64_t INF = 5e15;
const int INF2 = 1e9;
const int mod = 1e9+7;
const ld eps = 1e-6;

const int N = 1e5 + 2323;
const int D = 500;

std::vector<std::vector<int>> solve(int n);

// DO NOT COPY THE CODE BELOW THIS COMMENT TO YOUR SUBMISSION!
// Не копируйте код под этим комментарием в ваше решение!
struct Triangle {
    int i, j, k;

    Triangle() = default;
    Triangle(int i_, int j_, int k_) : i(i_), j(j_), k(k_) {}
};

int compare(const std::vector<Triangle>& left, const std::vector<Triangle>& right);

namespace {
    constexpr int kMaxQ = 2'000'000;
    int verbose = 0;

    void WA(const string& msg) {
        cout << "WA " << msg << "\n";
        exit(0);
    }

    int n, group;
    vector<pair<int64_t, int64_t>> points;
    uint64_t cur_queries;

    void ValidateTriangle(const Triangle& t) {
        if (t.i < 0 || t.i >= n) {
            WA("triangle i is out of range [0,n-1]");
        }
        if (t.j < 0 || t.j >= n) {
            WA("triangle j is out of range [0,n-1]");
        }
        if (t.k < 0 || t.k >= n) {
            WA("triangle k is out of range [0,n-1]");
        }
        if (t.i == t.j) {
            WA("triangle i and j are equal");
        }
        if (t.i == t.k) {
            WA("triangle i and k are equal");
        }
        if (t.j == t.k) {
            WA("triangle j and k are equal");
        }
    }

    uint64_t GetDoubleArea(const Triangle& t) {
        pair<int64_t, int64_t> v1 = {points[t.j].first - points[t.i].first, points[t.j].second - points[t.i].second};
        pair<int64_t, int64_t> v2 = {points[t.k].first - points[t.i].first, points[t.k].second - points[t.i].second};
        return abs(v1.first * v2.second - v1.second * v2.first);
    }

    void LogCompare(const vector<Triangle>& left, const vector<Triangle>& right) {
        cout << "compare #" << cur_queries << ":\n";
        cout << "left " << left.size() << " triangle" << (left.size() > 1 ? "s" : "") << ": ";
        for (size_t i = 0; i < left.size(); ++i) {
            cout << (i == 0 ? "(" : ", (") << left[i].i << "," << left[i].j << "," << left[i].k << ")";
        }
        cout << "\n";
        cout << "right " << right.size() << " triangle" << (right.size() > 1 ? "s" : "") << ": ";
        for (size_t i = 0; i < left.size(); ++i) {
            cout << (i == 0 ? "(" : ", (") << right[i].i << "," << right[i].j << "," << right[i].k << ")";
        }
        cout << "\n";
    }
}

int compare(const vector<Triangle>& left, const vector<Triangle>& right) {
    cur_queries++;
    if (cur_queries > kMaxQ) {
        WA("too many queries");
    }
    if (verbose > 0) {
        LogCompare(left, right);
    }
    if (left.empty()) {
        WA("left should be non-empty");
    }
    if (right.empty()) {
        WA("right should be non-empty");
    }
    if (left.size() + right.size() > 4) {
        WA("the number of triangles should be at most 4");
    }
    for (const auto& t : left) {
        ValidateTriangle(t);
    }
    for (const auto& t : right) {
        ValidateTriangle(t);
    }

    uint64_t left_area = 0;
    for (const auto& t : left) {
        left_area += GetDoubleArea(t);
    }
    uint64_t right_area = 0;
    for (const auto& t : right) {
        right_area += GetDoubleArea(t);
    }

    if (verbose > 0) {
        cout << "result: ";
        if (left_area < right_area) {
            cout << "left is smaller (-1)\n";
        } else if (left_area == right_area) {
            cout << "equal (0)\n";
        } else {
            cout << "right is smaller (1)\n";
        }
    }

    return left_area < right_area ? -1 : (left_area > right_area ? 1 : 0);
}


vector<vector<int>> solve(int n) {
    vvi ans;
    vi res;
    Triangle cur;
    vector<int> us(n);
    vector<Triangle> fi, si;

    for (int we = 0; we <= 100; we++) {
        Triangle mx = {-1, -1, -1};
        for (int i = 0; i < n; i++) {
            for (int j = 1; j <= 7; j++) {
                for (int k = j + 1; k <= 7 && i + k < n; k++) {
                    if (us[i] || us[i + j] || us[i + k]) continue;
                    cur = {i, i + j, i + k};
                    fi = {mx};
                    si = {cur};
                    if (mx.i == -1 || compare(fi, si) == -1) {
                        mx = cur;
                    }
                }
            }
        }
        if (mx.i == -1) continue;
        us[mx.i] = 1;
        us[mx.j] = 1;
        us[mx.k] = 1;
    }
    vi al;
    for (int i = 0; i < n; i++) {
        if (us[i]) al.pb(i);
    }
    Triangle mx = {-1, -1, -1};
    for (int i = 0; i < sz(al); i++) {
        for (int j = i + 1; j < sz(al); j++) {
            for (int k = j+ 1; k < sz(al); k++) {
                cur = {al[i], al[j], al[k]};
                fi = {mx};
                si = {cur};
                if (mx.i == -1 || compare(fi, si) == -1) {
                    mx = cur;
                }
            }
        }
    }
    res = {mx.i, mx.j, mx.k};
    ans.pb(res);
    return ans;
}


int main() {
    ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);

    cin >> n;
    points.resize(n);
    for (int i = 0; i < n; ++i) {
        cin >> points[i].first >> points[i].second;
    }
    cur_queries = 0;

    auto result = solve(n);

    cout << result.size() << "\n";
    for (const auto& polygon : result) {
        cout << polygon.size() << "\n";
        for (size_t i = 0; i < polygon.size(); ++i) {
            cout << polygon[i] << " \n"[i + 1 == polygon.size()];
        }
    }
    if (verbose > 0) {
        cout << cur_queries << (cur_queries == 1 ? " query\n" : " queries\n");
    }

    return 0;
}
