#include "triangles.h"
#include <iostream>
#include <vector>
#include <cstdint>
#include <bits/stdc++.h>

using namespace std;

#define sz(x) (int)x.size()

mt19937_64 rng(78620);



vector<vector<int>> fck(int ch0, int ch1, int ch2, vector<int> pp) {
    if (pp.empty()) {
        return {vector{ch0, ch1, ch2}};
    }
    int i = rng() % sz(pp);
    swap(pp[i], pp[0]);
    vector<int> p01, p12, p20;
    for (i = 1; i < sz(pp); ++i) {
        if (compare({Triangle(ch0, ch1, pp[0])},
            {Triangle(ch0, ch1, pp[i]), Triangle(ch1, pp[0], pp[i]), Triangle(pp[0], ch0, pp[i])}) == 0)
        {
            p01.emplace_back(i);
        }
        if (compare({Triangle(ch1, ch2, pp[0])},
            {Triangle(ch1, ch2, pp[i]), Triangle(ch2, pp[0], pp[i]), Triangle(pp[0], ch1, pp[i])}) == 0)
        {
            p12.emplace_back(i);
        }
        if (compare({Triangle(ch2, ch0, pp[0])},
            {Triangle(ch2, ch0, pp[i]), Triangle(ch0, pp[0], pp[i]), Triangle(pp[0], ch2, pp[i])}) == 0)
        {
            p20.emplace_back(i);
        }
    }
    auto res = fck(ch0, ch1, pp[0], p01);
    auto sub = fck(ch1, ch2, pp[0], p12);
    res.insert(res.end(), sub.begin(), sub.end());
    sub = fck(ch2, ch0, pp[0], p20);
    res.insert(res.end(), sub.begin(), sub.end());
    return res;
}

vector<vector<int>> solve(int n) {
    int ch0 = 2;
    for (int i = 3; i < n; ++i) {
        if (compare({Triangle(0, 1, ch0)}, {Triangle(0, 1, i)}) == -1) {
            ch0 = i;
        }
    }
    int ch1 = 1;
    for (int i = 2; i < n; ++i) {
        if (i != ch0 && compare({Triangle(0, ch0, ch1)}, {Triangle(0, ch0, i)}) == -1) {
            ch1 = i;
        }
    }
    int ch2 = 0;
    for (int i = 1; i < n; ++i) {
        if (i != ch0 && i != ch1 && compare({Triangle(ch0, ch1, ch2)}, {Triangle(ch0, ch1, i)}) == -1) {
            ch2 = i;
        }
    }
    vector<int> pp;
    pp.reserve(n - 3);
    for (int i = 0; i < n; ++i) {
        if (i != ch0 && i != ch1 && i != ch2) {
            pp.emplace_back(i);
        }
    }
    return fck(ch0, ch1, ch2, pp);
}

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);
}

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;
}
