#include "triangles.h"
#include <iostream>
#include <vector>
#include <cstdint>

using namespace std;

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


// #pragma GCC optimize("O3,unroll-loops")
// #pragma GCC target("avx2,bmi,bmi2,popcnt,lzcnt")

// #pragma clang __attribute__(optimize("O3,unroll-loops"))
// #pragma clang __attribute__(target("avx2,bmi,bmi2,popcnt,lzcnt"))

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

typedef long long ll;
typedef long double ld;
typedef __int128 lll;

const ll inf=1e18+1,mod=998244353;
const ld eps=1e-9,pi=acos(-1);
#define all(a) a.begin(), a.end()
#define mpp make_pair
#define F first
#define S second

mt19937_64 rng(234);

// You should implement
// Вам необходимо реализовать

ll in(Triangle t0,ll j) {
    ll i0=t0.i,i1=t0.j,i2=t0.k;
    if (i0==j||i1==j||i2==j)
        return -1;
    Triangle a(i0,i1,j);
    Triangle b(i0,i2,j);
    Triangle c(i2,i1,j);
    return (compare({t0},{a,b,c})==0);
}

bool check(ll a,ll b,ll i2,ll j) {
    Triangle ta(a,b,j);
    Triangle tb(a,i2,j);
    Triangle tc(i2,b,j);
    Triangle t(a,b,i2);
    if (in(ta,i2))
        return 0;
    if (in(tb,b))
        return 1;
    if (in(tc,a))
        return 1;
    return (compare({t,ta},{tb,tc})==0);
}


bool checkas(ll a,ll b,ll i2,ll j) {
    Triangle ta(a,b,j);
    Triangle tb(a,i2,j);
    Triangle tc(i2,b,j);
    Triangle t(a,b,i2);
    if (in(ta,i2))
    return 0;
    if (in(tb,b))
        return 1;
    if (in(tc,a))
        return 1;
    return (compare({t,ta},{tb,tc})==0);
}

std::vector<std::vector<int>> solve(int n) {
    vector<Triangle>trn(1,Triangle(0,1,2));
    vector<ll>hull={0,1,2};
    for (ll i=3;i<n;i++) {
        vector<Triangle>nw;
        ll m=hull.size();
        vector<ll>kl(n);
        ll any=0;
        for (ll j=0;j<hull.size();j++) {
            ll pa=hull[j];
            ll pb=(hull[(j+1)%m]);
            ll pn=(hull[(j+2)%m]);
            if (check(pa,pb,pn,i)) {
                ll pn2=hull[(j-1+m)%m];
                if (check(pa,pb,pn2,i)) {
                    nw.push_back(Triangle(pa,pb,i));
                    kl[pa]++;
                    kl[pb]++;
                    any=1;
                }else {
                    checkas(pa,pb,pn2,i);
                }
            }
        }
        if (!any) {
            // trn.clear();
            // trn.push_back(Triangle(0,1,3));
            // trn.push_back(Triangle(2,1,3));
            // trn.push_back(Triangle(0,2,3));
            continue;
        }
        ll ok=0;
        vector<ll>nwh;
        for (ll j=0;j<hull.size();j++)
            if (kl[hull[j]]<2) {
                nwh.push_back(hull[j]);
                if (kl[hull[j]]==1) {
                    if (!ok)
                        nwh.push_back(i);
                    ok=1;
                }
            }
        hull=nwh;
        for (auto it:nw)
            trn.push_back(it);
    }
    vector<vector<int>>ans;
    for (auto i:trn)
        ans.push_back({i.i,i.j,i.k});
    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;
}
