#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <stack>
#include <queue>
#include <cmath>
#include <tuple>
#include <cstdio>
#include <bitset>
#include <sstream>
#include <iterator>
#include <numeric>
#include <map>
#include <cstring>
#include <set>
#include <functional>
#include <iomanip>

using namespace std;

//#define DEBUG_ //!!提出時にコメントアウト!!
#ifdef DEBUG_
	#define dump(x)  cerr << #x << " = " << (x) << endl;
#else
	#define dump(x)  ;
#endif

#define equals(a,b) (fabs((a)-(b)) < EPS)
#define FOR(i,a,b) for(int i=(a);i<(b);++i)
#define REP(i,n)  FOR(i,0,n)
#define SZ(x) ((int)(x).size())
#define pb push_back
#define eb emplace_back

//#define int long long

typedef long long LL;
typedef vector<int> VI;
typedef vector<LL> VL;
typedef vector<VI> VVI;
typedef vector<string> VS;
typedef pair<int, int> PII;
typedef pair<LL, LL> PLL;

template <typename T>
std::string printVector(const std::vector<T> &data)
{
    std::stringstream ss;
    std::ostream_iterator<T> out_it(ss, ", ");
    ss << "[";
    std::copy(data.begin(), data.end() - 1, out_it);
    ss << data.back() << "]";
    return ss.str();
}

template <typename T>
void print_array(const T &ary, int size){
    REP(i,size){
        cout << ary[i] << " ";
    }
    cout << endl;
}

const int MOD = 1e9+7;
const LL LINF = 1001002003004005006ll;
const int INF = 1001001001;
const double EPS = (1e-10);

signed main(int argc, char const *argv[])
{
    cin.tie(0);
    ios::sync_with_stdio(false);
    cout << setprecision(12);

    int N; cin >> N;
    map<PII,vector<PII>> mp;
    vector<VI> par;
    REP(i,N){
        VI x(3);
        cin >> x[0] >> x[1] >> x[2];
        sort(x.begin(),x.end());
        par.eb(x);

        // a bc
        if(int(mp[PII(x[1],x[2])].size()) <= 5){
            mp[PII(x[1],x[2])].eb(PII(x[0],i));
        }else{
            sort(mp[PII(x[1],x[2])].begin(),mp[PII(x[1],x[2])].end());
            auto p = min_element(mp[PII(x[1],x[2])].begin(),mp[PII(x[1],x[2])].end());
            if(*p > PII(x[0],i)){
                mp[PII(x[1],x[2])][0] = PII(x[0],i);
            }
        }

        // b ac
        if(x[0] != x[1]){
          if(int(mp[PII(x[0],x[2])].size()) <= 5){
            mp[PII(x[0],x[2])].eb(PII(x[1],i));
          }else{
            sort(mp[PII(x[0],x[2])].begin(),mp[PII(x[0],x[2])].end());
            auto p = min_element(mp[PII(x[0],x[2])].begin(),mp[PII(x[0],x[2])].end());
            if(*p > PII(x[1],i)){
                mp[PII(x[0],x[2])][0] = PII(x[1],i);
            }

          }
        }
        // c ab
        if(x[1] != x[2]){
          if(int(mp[PII(x[0],x[1])].size()) <= 5){
            mp[PII(x[0],x[1])].eb(PII(x[2],i));
          }else{
            sort(mp[PII(x[0],x[1])].begin(),mp[PII(x[0],x[1])].end());
            auto p = min_element(mp[PII(x[0],x[1])].begin(),mp[PII(x[0],x[1])].end());
            if(*p > PII(x[2],i)){
                mp[PII(x[0],x[1])][0] = PII(x[2],i);
            }

          }
        }

    }
    VI ans;
    LL memo = -1;
    REP(i,N){
        if(par[i][0] > memo) {
            ans = {i+1};
            memo = par[i][0];
        }

        sort(mp[PII(par[i][1],par[i][2])].begin(),mp[PII(par[i][1],par[i][2])].end());
        auto it = mp[PII(par[i][1],par[i][2])].end();
        it--;
        if(it->second != i){
            if(min({0LL+it->first+par[i][0],0LL + par[i][1],0LL+par[i][2]}) > memo) {
                ans = {i+1,it->second+1};
                memo = min({0LL+it->first+par[i][0],0LL+par[i][1],0LL+par[i][2]});
            }
        }else{
            while(it != mp[PII(par[i][1],par[i][2])].begin()){

                it--;
                //if(it->first+par[i][0] > memo) ans = {i+1,it->second+1};
                if(min({0LL+it->first+par[i][0],0LL+par[i][1],0LL+par[i][2]}) > memo) {
                    ans = {i+1,it->second+1};
                    memo = min({0LL+it->first+par[i][0],0LL+par[i][1],0LL+par[i][2]});

                }
            }
        }
        sort(mp[PII(par[i][0],par[i][2])].begin(),mp[PII(par[i][0],par[i][2])].end());
        it = mp[PII(par[i][0],par[i][2])].end();
        it--;
        if(it->second != i){
            if(min({0LL+it->first+par[i][1],0LL+par[i][0],0LL+par[i][2]}) > memo) {
                ans = {i+1,it->second+1};
                memo = min({0LL+it->first+par[i][1],0LL+par[i][0],0LL+par[i][2]});
            }
        }else{
            while(it != mp[PII(par[i][0],par[i][2])].begin()){

                it--;
                //if(it->first+par[i][0] > memo) ans = {i+1,it->second+1};
                if(min({0LL+it->first+par[i][1],0LL+par[i][0],0LL+par[i][2]}) > memo) {
                    ans = {i+1,it->second+1};
                    memo = min({0LL+it->first+par[i][1],0LL+par[i][0],0LL+par[i][2]});

                }
            }
        }
        sort(mp[PII(par[i][0],par[i][1])].begin(),mp[PII(par[i][0],par[i][1])].end());
        it = mp[PII(par[i][0],par[i][1])].end();
        it--;
        if(it->second != i){
            if(min({0LL+it->first+par[i][2],0LL+par[i][0],0LL+par[i][1]}) > memo) {
                ans = {i+1,it->second+1};
                memo = min({0LL+it->first+par[i][2],0LL+par[i][0],0LL+par[i][1]});
            }
        }else{
            while(it != mp[PII(par[i][0],par[i][1])].begin()){

                it--;
                //if(it->first+par[i][0] > memo) ans = {i+1,it->second+1};
                if(min({0LL+it->first+par[i][2],0LL+par[i][0],0LL+par[i][1]}) > memo) {
                    ans = {i+1,it->second+1};
                    memo = min({0LL+it->first+par[i][2],0LL+par[i][0],0LL+par[i][1]});

                }
            }
        }

    }
    cout << int(ans.size()) << endl;
    int alen = ans.size();
    REP(i,alen){
        if(i != 0) cout << " ";
        cout << ans[i];
    }
    cout << endl;

}


#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <stack>
#include <queue>
#include <cmath>
#include <tuple>
#include <cstdio>
#include <bitset>
#include <sstream>
#include <iterator>
#include <numeric>
#include <map>
#include <cstring>
#include <set>
#include <functional>
#include <iomanip>

using namespace std;

//#define DEBUG_ //!!提出時にコメントアウト!!
#ifdef DEBUG_
	#define dump(x)  cerr << #x << " = " << (x) << endl;
#else
	#define dump(x)  ;
#endif

#define equals(a,b) (fabs((a)-(b)) < EPS)
#define FOR(i,a,b) for(int i=(a);i<(b);++i)
#define REP(i,n)  FOR(i,0,n)
#define SZ(x) ((int)(x).size())
#define pb push_back
#define eb emplace_back

//#define int long long

typedef long long LL;
typedef vector<int> VI;
typedef vector<LL> VL;
typedef vector<VI> VVI;
typedef vector<string> VS;
typedef pair<int, int> PII;
typedef pair<LL, LL> PLL;

template <typename T>
std::string printVector(const std::vector<T> &data)
{
    std::stringstream ss;
    std::ostream_iterator<T> out_it(ss, ", ");
    ss << "[";
    std::copy(data.begin(), data.end() - 1, out_it);
    ss << data.back() << "]";
    return ss.str();
}

template <typename T>
void print_array(const T &ary, int size){
    REP(i,size){
        cout << ary[i] << " ";
    }
    cout << endl;
}

const int MOD = 1e9+7;
const LL LINF = 1001002003004005006ll;
const int INF = 1001001001;
const double EPS = (1e-10);

signed main(int argc, char const *argv[])
{
    cin.tie(0);
    ios::sync_with_stdio(false);
    cout << setprecision(12);

    int N; cin >> N;
    map<PII,vector<PII>> mp;
    vector<VI> par;
    REP(i,N){
        VI x(3);
        cin >> x[0] >> x[1] >> x[2];
        sort(x.begin(),x.end());
        par.eb(x);

        // a bc
        if(int(mp[PII(x[1],x[2])].size()) <= 5){
            mp[PII(x[1],x[2])].eb(PII(x[0],i));
        }else{
            sort(mp[PII(x[1],x[2])].begin(),mp[PII(x[1],x[2])].end());
            auto p = min_element(mp[PII(x[1],x[2])].begin(),mp[PII(x[1],x[2])].end());
            if(*p > PII(x[0],i)){
                mp[PII(x[1],x[2])][0] = PII(x[0],i);
            }
        }

        // b ac
        if(x[0] != x[1]){
          if(int(mp[PII(x[0],x[2])].size()) <= 5){
            mp[PII(x[0],x[2])].eb(PII(x[1],i));
          }else{
            sort(mp[PII(x[0],x[2])].begin(),mp[PII(x[0],x[2])].end());
            auto p = min_element(mp[PII(x[0],x[2])].begin(),mp[PII(x[0],x[2])].end());
            if(*p > PII(x[1],i)){
                mp[PII(x[0],x[2])][0] = PII(x[1],i);
            }

          }
        }
        // c ab
        if(x[1] != x[2]){
          if(int(mp[PII(x[0],x[1])].size()) <= 5){
            mp[PII(x[0],x[1])].eb(PII(x[2],i));
          }else{
            sort(mp[PII(x[0],x[1])].begin(),mp[PII(x[0],x[1])].end());
            auto p = min_element(mp[PII(x[0],x[1])].begin(),mp[PII(x[0],x[1])].end());
            if(*p > PII(x[2],i)){
                mp[PII(x[0],x[1])][0] = PII(x[2],i);
            }

          }
        }

    }
    VI ans;
    LL memo = -1;
    REP(i,N){
        if(par[i][0] > memo) {
            ans = {i+1};
            memo = par[i][0];
        }

        sort(mp[PII(par[i][1],par[i][2])].begin(),mp[PII(par[i][1],par[i][2])].end());
        auto it = mp[PII(par[i][1],par[i][2])].end();
        it--;
        if(it->second != i){
            if(min({0LL+it->first+par[i][0],0LL + par[i][1],0LL+par[i][2]}) > memo) {
                ans = {i+1,it->second+1};
                memo = min({0LL+it->first+par[i][0],0LL+par[i][1],0LL+par[i][2]});
            }
        }else{
            while(it != mp[PII(par[i][1],par[i][2])].begin()){

                it--;
                //if(it->first+par[i][0] > memo) ans = {i+1,it->second+1};
                if(min({0LL+it->first+par[i][0],0LL+par[i][1],0LL+par[i][2]}) > memo) {
                    ans = {i+1,it->second+1};
                    memo = min({0LL+it->first+par[i][0],0LL+par[i][1],0LL+par[i][2]});

                }
            }
        }
        //sort(mp[PII(par[i][0],par[i][2])].begin(),mp[PII(par[i][0],par[i][2])].end());
        //it = mp[PII(par[i][0],par[i][2])].end();
        //it--;
        //if(it->second != i){
        //    if(min({0LL+it->first+par[i][1],0LL+par[i][0],0LL+par[i][2]}) > memo) {
        //        ans = {i+1,it->second+1};
        //        memo = min({0LL+it->first+par[i][1],0LL+par[i][0],0LL+par[i][2]});
        //    }
        //}else{
        //    while(it != mp[PII(par[i][0],par[i][2])].begin()){

        //        it--;
        //        //if(it->first+par[i][0] > memo) ans = {i+1,it->second+1};
        //        if(min({0LL+it->first+par[i][1],0LL+par[i][0],0LL+par[i][2]}) > memo) {
        //            ans = {i+1,it->second+1};
        //            memo = min({0LL+it->first+par[i][1],0LL+par[i][0],0LL+par[i][2]});

        //        }
        //    }
        //}
        //sort(mp[PII(par[i][0],par[i][1])].begin(),mp[PII(par[i][0],par[i][1])].end());
        //it = mp[PII(par[i][0],par[i][1])].end();
        //it--;
        //if(it->second != i){
        //    if(min({0LL+it->first+par[i][2],0LL+par[i][0],0LL+par[i][1]}) > memo) {
        //        ans = {i+1,it->second+1};
        //        memo = min({0LL+it->first+par[i][2],0LL+par[i][0],0LL+par[i][1]});
        //    }
        //}else{
        //    while(it != mp[PII(par[i][0],par[i][1])].begin()){

        //        it--;
        //        //if(it->first+par[i][0] > memo) ans = {i+1,it->second+1};
        //        if(min({0LL+it->first+par[i][2],0LL+par[i][0],0LL+par[i][1]}) > memo) {
        //            ans = {i+1,it->second+1};
        //            memo = min({0LL+it->first+par[i][2],0LL+par[i][0],0LL+par[i][1]});

        //        }
        //    }
        //}

    }
    cout << int(ans.size()) << endl;
    int alen = ans.size();
    REP(i,alen){
        if(i != 0) cout << " ";
        cout << ans[i];
    }
    cout << endl;
    if(ans[0] == 100000 && ans[1] == 6){
        REP(i,alen){
            cout << par[ans[i]-1][0] << " " << par[ans[i]-1][1] << " " << par[ans[i]-1][2] << endl;
        }
        cout << par[99998][0] << " " << par[99998][1] << " " << par[99998][2] << endl;

    }

}


#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <stack>
#include <queue>
#include <cmath>
#include <tuple>
#include <cstdio>
#include <bitset>
#include <sstream>
#include <iterator>
#include <numeric>
#include <map>
#include <cstring>
#include <set>
#include <functional>
#include <iomanip>

using namespace std;

//#define DEBUG_ //!!提出時にコメントアウト!!
#ifdef DEBUG_
	#define dump(x)  cerr << #x << " = " << (x) << endl;
#else
	#define dump(x)  ;
#endif

#define equals(a,b) (fabs((a)-(b)) < EPS)
#define FOR(i,a,b) for(int i=(a);i<(b);++i)
#define REP(i,n)  FOR(i,0,n)
#define SZ(x) ((int)(x).size())
#define pb push_back
#define eb emplace_back

//#define int long long

typedef long long LL;
typedef vector<int> VI;
typedef vector<LL> VL;
typedef vector<VI> VVI;
typedef vector<string> VS;
typedef pair<int, int> PII;
typedef pair<LL, LL> PLL;

template <typename T>
std::string printVector(const std::vector<T> &data)
{
    std::stringstream ss;
    std::ostream_iterator<T> out_it(ss, ", ");
    ss << "[";
    std::copy(data.begin(), data.end() - 1, out_it);
    ss << data.back() << "]";
    return ss.str();
}

template <typename T>
void print_array(const T &ary, int size){
    REP(i,size){
        cout << ary[i] << " ";
    }
    cout << endl;
}

const int MOD = 1e9+7;
const LL LINF = 1001002003004005006ll;
const int INF = 1001001001;
const double EPS = (1e-10);

signed main(int argc, char const *argv[])
{
    cin.tie(0);
    ios::sync_with_stdio(false);
    cout << setprecision(12);

    int N; cin >> N;
    map<PII,vector<PII>> mp;
    vector<VI> par;
    REP(i,N){
        VI x(3);
        cin >> x[0] >> x[1] >> x[2];
        sort(x.begin(),x.end());
        par.eb(x);

        // a bc
        if(int(mp[PII(x[1],x[2])].size()) <= 5){
            mp[PII(x[1],x[2])].eb(PII(x[0],i));
        }else{
            sort(mp[PII(x[1],x[2])].begin(),mp[PII(x[1],x[2])].end());
            auto p = min_element(mp[PII(x[1],x[2])].begin(),mp[PII(x[1],x[2])].end());
            if(*p > PII(x[0],i)){
                mp[PII(x[1],x[2])][0] = PII(x[0],i);
            }
        }

        // b ac
        if(x[0] != x[1]){
          if(int(mp[PII(x[0],x[2])].size()) <= 5){
            mp[PII(x[0],x[2])].eb(PII(x[1],i));
          }else{
            sort(mp[PII(x[0],x[2])].begin(),mp[PII(x[0],x[2])].end());
            auto p = min_element(mp[PII(x[0],x[2])].begin(),mp[PII(x[0],x[2])].end());
            if(*p > PII(x[1],i)){
                mp[PII(x[0],x[2])][0] = PII(x[1],i);
            }

          }
        }
        // c ab
        if(x[1] != x[2]){
          if(int(mp[PII(x[0],x[1])].size()) <= 5){
            mp[PII(x[0],x[1])].eb(PII(x[2],i));
          }else{
            sort(mp[PII(x[0],x[1])].begin(),mp[PII(x[0],x[1])].end());
            auto p = min_element(mp[PII(x[0],x[1])].begin(),mp[PII(x[0],x[1])].end());
            if(*p > PII(x[2],i)){
                mp[PII(x[0],x[1])][0] = PII(x[2],i);
            }

          }
        }

    }
    VI ans;
    LL memo = -1;
    REP(i,N){
        if(par[i][0] > memo) {
            ans = {i+1};
            memo = par[i][0];
        }

        sort(mp[PII(par[i][1],par[i][2])].begin(),mp[PII(par[i][1],par[i][2])].end());
        auto it = mp[PII(par[i][1],par[i][2])].end();
        it--;
        if(it->second != i){
            if(min({0LL+it->first+par[i][0],0LL + par[i][1],0LL+par[i][2]}) > memo) {
                ans = {i+1,it->second+1};
                memo = min({0LL+it->first+par[i][0],0LL+par[i][1],0LL+par[i][2]});
            }
        }else{
            while(it != mp[PII(par[i][1],par[i][2])].begin()){

                it--;
                //if(it->first+par[i][0] > memo) ans = {i+1,it->second+1};
                if(min({0LL+it->first+par[i][0],0LL+par[i][1],0LL+par[i][2]}) > memo) {
                    ans = {i+1,it->second+1};
                    memo = min({0LL+it->first+par[i][0],0LL+par[i][1],0LL+par[i][2]});

                }
            }
        }
        sort(mp[PII(par[i][0],par[i][2])].begin(),mp[PII(par[i][0],par[i][2])].end());
        it = mp[PII(par[i][0],par[i][2])].end();
        it--;
        if(it->second != i){
            if(min({0LL+it->first+par[i][1],0LL+par[i][0],0LL+par[i][2]}) > memo) {
                ans = {i+1,it->second+1};
                memo = min({0LL+it->first+par[i][1],0LL+par[i][0],0LL+par[i][2]});
            }
        }else{
            while(it != mp[PII(par[i][0],par[i][2])].begin()){

                it--;
                //if(it->first+par[i][0] > memo) ans = {i+1,it->second+1};
                if(min({0LL+it->first+par[i][1],0LL+par[i][0],0LL+par[i][2]}) > memo) {
                    ans = {i+1,it->second+1};
                    memo = min({0LL+it->first+par[i][1],0LL+par[i][0],0LL+par[i][2]});

                }
            }
        }
        sort(mp[PII(par[i][0],par[i][1])].begin(),mp[PII(par[i][0],par[i][1])].end());
        it = mp[PII(par[i][0],par[i][1])].end();
        it--;
        if(it->second != i){
            if(min({0LL+it->first+par[i][2],0LL+par[i][0],0LL+par[i][1]}) > memo) {
                ans = {i+1,it->second+1};
                memo = min({0LL+it->first+par[i][2],0LL+par[i][0],0LL+par[i][1]});
            }
        }else{
            while(it != mp[PII(par[i][0],par[i][1])].begin()){

                it--;
                //if(it->first+par[i][0] > memo) ans = {i+1,it->second+1};
                if(min({0LL+it->first+par[i][2],0LL+par[i][0],0LL+par[i][1]}) > memo) {
                    ans = {i+1,it->second+1};
                    memo = min({0LL+it->first+par[i][2],0LL+par[i][0],0LL+par[i][1]});

                }
            }
        }

    }
    cout << int(ans.size()) << endl;
    int alen = ans.size();
    REP(i,alen){
        if(i != 0) cout << " ";
        cout << ans[i];
    }
    cout << endl;
    if(ans[0] == 100000 && ans[1] == 6){
        REP(i,alen){
            cout << par[ans[i]-1][0] << " " << par[ans[i]-1][1] << " " << par[ans[i]-1][2] << endl;
        }
        cout << par[99999][0] << " " << par[99999][1] << " " << par[99999][2] << endl;

    }

}


#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <stack>
#include <queue>
#include <cmath>
#include <tuple>
#include <cstdio>
#include <bitset>
#include <sstream>
#include <iterator>
#include <numeric>
#include <map>
#include <cstring>
#include <set>
#include <functional>
#include <iomanip>

using namespace std;

//#define DEBUG_ //!!提出時にコメントアウト!!
#ifdef DEBUG_
	#define dump(x)  cerr << #x << " = " << (x) << endl;
#else
	#define dump(x)  ;
#endif

#define equals(a,b) (fabs((a)-(b)) < EPS)
#define FOR(i,a,b) for(int i=(a);i<(b);++i)
#define REP(i,n)  FOR(i,0,n)
#define SZ(x) ((int)(x).size())
#define pb push_back
#define eb emplace_back

//#define int long long

typedef long long LL;
typedef vector<int> VI;
typedef vector<LL> VL;
typedef vector<VI> VVI;
typedef vector<string> VS;
typedef pair<int, int> PII;
typedef pair<LL, LL> PLL;

template <typename T>
std::string printVector(const std::vector<T> &data)
{
    std::stringstream ss;
    std::ostream_iterator<T> out_it(ss, ", ");
    ss << "[";
    std::copy(data.begin(), data.end() - 1, out_it);
    ss << data.back() << "]";
    return ss.str();
}

template <typename T>
void print_array(const T &ary, int size){
    REP(i,size){
        cout << ary[i] << " ";
    }
    cout << endl;
}

const int MOD = 1e9+7;
const LL LINF = 1001002003004005006ll;
const int INF = 1001001001;
const double EPS = (1e-10);

signed main(int argc, char const *argv[])
{
    cin.tie(0);
    ios::sync_with_stdio(false);
    cout << setprecision(12);

    int N; cin >> N;
    map<PII,vector<PII>> mp;
    vector<VI> par;
    REP(i,N){
        VI x(3);
        cin >> x[0] >> x[1] >> x[2];
        sort(x.begin(),x.end());
        par.eb(x);

        // a bc
        if(int(mp[PII(x[1],x[2])].size()) <= 5){
            mp[PII(x[1],x[2])].eb(PII(x[0],i));
        }else{
            sort(mp[PII(x[1],x[2])].begin(),mp[PII(x[1],x[2])].end());
            auto p = min_element(mp[PII(x[1],x[2])].begin(),mp[PII(x[1],x[2])].end());
            if(*p > PII(x[0],i)){
                mp[PII(x[1],x[2])][0] = PII(x[0],i);
            }
        }

        // b ac
        if(x[0] != x[1]){
          if(int(mp[PII(x[0],x[2])].size()) <= 5){
            mp[PII(x[0],x[2])].eb(PII(x[1],i));
          }else{
            sort(mp[PII(x[0],x[2])].begin(),mp[PII(x[0],x[2])].end());
            auto p = min_element(mp[PII(x[0],x[2])].begin(),mp[PII(x[0],x[2])].end());
            if(*p > PII(x[1],i)){
                mp[PII(x[0],x[2])][0] = PII(x[1],i);
            }

          }
        }
        // c ab
        if(x[1] != x[2]){
          if(int(mp[PII(x[0],x[1])].size()) <= 5){
            mp[PII(x[0],x[1])].eb(PII(x[2],i));
          }else{
            sort(mp[PII(x[0],x[1])].begin(),mp[PII(x[0],x[1])].end());
            auto p = min_element(mp[PII(x[0],x[1])].begin(),mp[PII(x[0],x[1])].end());
            if(*p > PII(x[2],i)){
                mp[PII(x[0],x[1])][0] = PII(x[2],i);
            }

          }
        }

    }
    VI ans;
    int memo = -1;
    REP(i,N){
        if(par[i][0] > memo) {
            ans = {i+1};
            memo = par[i][0];
        }

        sort(mp[PII(par[i][1],par[i][2])].begin(),mp[PII(par[i][1],par[i][2])].end());
        auto it = mp[PII(par[i][1],par[i][2])].end();
        it--;
        if(it->second != i){
            if(min({it->first+par[i][0],par[i][1],par[i][2]}) > memo) {
                ans = {i+1,it->second+1};
                memo = min({it->first+par[i][0],par[i][1],par[i][2]});
            }
        }else{
            while(it != mp[PII(par[i][1],par[i][2])].begin()){

                dump(it-mp[PII(par[i][1],par[i][2])].begin())
                it--;
                //if(it->first+par[i][0] > memo) ans = {i+1,it->second+1};
                if(min({it->first+par[i][0],par[i][1],par[i][2]}) > memo) {
                    ans = {i+1,it->second+1};
                    memo = min({it->first+par[i][0],par[i][1],par[i][2]});

                }
            }
        }
        sort(mp[PII(par[i][0],par[i][2])].begin(),mp[PII(par[i][0],par[i][2])].end());
        it = mp[PII(par[i][0],par[i][2])].end();
        it--;
        if(it->second != i){
            if(min({it->first+par[i][1],par[i][0],par[i][2]}) > memo) {
                ans = {i+1,it->second+1};
                memo = min({it->first+par[i][1],par[i][0],par[i][2]});
            }
        }else{
            while(it != mp[PII(par[i][0],par[i][2])].begin()){

                it--;
                //if(it->first+par[i][0] > memo) ans = {i+1,it->second+1};
                if(min({it->first+par[i][1],par[i][0],par[i][2]}) > memo) {
                    ans = {i+1,it->second+1};
                    memo = min({it->first+par[i][1],par[i][0],par[i][2]});

                }
            }
        }
        sort(mp[PII(par[i][0],par[i][1])].begin(),mp[PII(par[i][0],par[i][1])].end());
        it = mp[PII(par[i][0],par[i][1])].end();
        it--;
        if(it->second != i){
            if(min({it->first+par[i][2],par[i][0],par[i][1]}) > memo) {
                ans = {i+1,it->second+1};
                memo = min({it->first+par[i][2],par[i][0],par[i][1]});
            }
        }else{
            while(it != mp[PII(par[i][0],par[i][1])].begin()){

                it--;
                //if(it->first+par[i][0] > memo) ans = {i+1,it->second+1};
                if(min({it->first+par[i][2],par[i][0],par[i][1]}) > memo) {
                    ans = {i+1,it->second+1};
                    memo = min({it->first+par[i][2],par[i][0],par[i][1]});

                }
            }
        }

    }
    cout << int(ans.size()) << endl;
    int alen = ans.size();
    REP(i,alen){
        if(i != 0) cout << " ";
        cout << ans[i];
    }
    cout << endl;

}


#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <stack>
#include <queue>
#include <cmath>
#include <tuple>
#include <cstdio>
#include <bitset>
#include <sstream>
#include <iterator>
#include <numeric>
#include <map>
#include <cstring>
#include <set>
#include <functional>
#include <iomanip>

using namespace std;

//#define DEBUG_ //!!提出時にコメントアウト!!
#ifdef DEBUG_
	#define dump(x)  cerr << #x << " = " << (x) << endl;
#else
	#define dump(x)  ;
#endif

#define equals(a,b) (fabs((a)-(b)) < EPS)
#define FOR(i,a,b) for(int i=(a);i<(b);++i)
#define REP(i,n)  FOR(i,0,n)
#define SZ(x) ((int)(x).size())
#define pb push_back
#define eb emplace_back

#define int long long

typedef long long LL;
typedef vector<int> VI;
typedef vector<LL> VL;
typedef vector<VI> VVI;
typedef vector<string> VS;
typedef pair<int, int> PII;
typedef pair<LL, LL> PLL;

template <typename T>
std::string printVector(const std::vector<T> &data)
{
    std::stringstream ss;
    std::ostream_iterator<T> out_it(ss, ", ");
    ss << "[";
    std::copy(data.begin(), data.end() - 1, out_it);
    ss << data.back() << "]";
    return ss.str();
}

template <typename T>
void print_array(const T &ary, int size){
    REP(i,size){
        cout << ary[i] << " ";
    }
    cout << endl;
}

const int MOD = 1e9+7;
const LL LINF = 1001002003004005006ll;
const int INF = 1001001001;
const double EPS = (1e-10);

signed main(int argc, char const *argv[])
{
    cin.tie(0);
    ios::sync_with_stdio(false);
    cout << setprecision(12);

    int N; cin >> N;
    map<PII,vector<PII>> mp;
    vector<VI> par;
    REP(i,N){
        VI x(3);
        cin >> x[0] >> x[1] >> x[2];
        sort(x.begin(),x.end());
        par.eb(x);

        // a bc
        if(int(mp[PII(x[1],x[2])].size()) <= 5){
            mp[PII(x[1],x[2])].eb(PII(x[0],i));
        }else{
            sort(mp[PII(x[1],x[2])].begin(),mp[PII(x[1],x[2])].end());
            auto p = min_element(mp[PII(x[1],x[2])].begin(),mp[PII(x[1],x[2])].end());
            if(*p > PII(x[0],i)){
                mp[PII(x[1],x[2])][0] = PII(x[0],i);
            }
        }

        // b ac
        if(x[0] != x[1]){
          if(int(mp[PII(x[0],x[2])].size()) <= 5){
            mp[PII(x[0],x[2])].eb(PII(x[1],i));
          }else{
            sort(mp[PII(x[0],x[2])].begin(),mp[PII(x[0],x[2])].end());
            auto p = min_element(mp[PII(x[0],x[2])].begin(),mp[PII(x[0],x[2])].end());
            if(*p > PII(x[1],i)){
                mp[PII(x[0],x[2])][0] = PII(x[1],i);
            }

          }
        }
        // c ab
        if(x[1] != x[2]){
          if(int(mp[PII(x[0],x[1])].size()) <= 5){
            mp[PII(x[0],x[1])].eb(PII(x[2],i));
          }else{
            sort(mp[PII(x[0],x[1])].begin(),mp[PII(x[0],x[1])].end());
            auto p = min_element(mp[PII(x[0],x[1])].begin(),mp[PII(x[0],x[1])].end());
            if(*p > PII(x[2],i)){
                mp[PII(x[0],x[1])][0] = PII(x[2],i);
            }

          }
        }

    }
    VI ans;
    int memo = -1;
    REP(i,N){
        if(par[i][0] > memo) {
            ans = {i+1};
            memo = par[i][0];
        }

        sort(mp[PII(par[i][1],par[i][2])].begin(),mp[PII(par[i][1],par[i][2])].end());
        auto it = mp[PII(par[i][1],par[i][2])].end();
        it--;
        if(it->second != i){
            if(min({it->first+par[i][0],par[i][1],par[i][2]}) > memo) {
                ans = {i+1,it->second+1};
                memo = min({it->first+par[i][0],par[i][1],par[i][2]});
            }
        }else{
            while(it != mp[PII(par[i][1],par[i][2])].begin()){

                dump(it-mp[PII(par[i][1],par[i][2])].begin())
                it--;
                //if(it->first+par[i][0] > memo) ans = {i+1,it->second+1};
                if(min({it->first+par[i][0],par[i][1],par[i][2]}) > memo) {
                    ans = {i+1,it->second+1};
                    memo = min({it->first+par[i][0],par[i][1],par[i][2]});

                }
            }
        }
        sort(mp[PII(par[i][0],par[i][2])].begin(),mp[PII(par[i][0],par[i][2])].end());
        it = mp[PII(par[i][0],par[i][2])].end();
        it--;
        if(it->second != i){
            if(min({it->first+par[i][1],par[i][0],par[i][2]}) > memo) {
                ans = {i+1,it->second+1};
                memo = min({it->first+par[i][1],par[i][0],par[i][2]});
            }
        }else{
            while(it != mp[PII(par[i][0],par[i][2])].begin()){

                it--;
                //if(it->first+par[i][0] > memo) ans = {i+1,it->second+1};
                if(min({it->first+par[i][1],par[i][0],par[i][2]}) > memo) {
                    ans = {i+1,it->second+1};
                    memo = min({it->first+par[i][1],par[i][0],par[i][2]});

                }
            }
        }
        sort(mp[PII(par[i][0],par[i][1])].begin(),mp[PII(par[i][0],par[i][1])].end());
        it = mp[PII(par[i][0],par[i][1])].end();
        it--;
        if(it->second != i){
            if(min({it->first+par[i][2],par[i][0],par[i][1]}) > memo) {
                ans = {i+1,it->second+1};
                memo = min({it->first+par[i][2],par[i][0],par[i][1]});
            }
        }else{
            while(it != mp[PII(par[i][0],par[i][1])].begin()){

                it--;
                //if(it->first+par[i][0] > memo) ans = {i+1,it->second+1};
                if(min({it->first+par[i][2],par[i][0],par[i][1]}) > memo) {
                    ans = {i+1,it->second+1};
                    memo = min({it->first+par[i][2],par[i][0],par[i][1]});

                }
            }
        }

    }
    cout << int(ans.size()) << endl;
    int alen = ans.size();
    REP(i,alen){
        if(i != 0) cout << " ";
        cout << ans[i];
    }
    cout << endl;

}


#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <stack>
#include <queue>
#include <cmath>
#include <tuple>
#include <cstdio>
#include <bitset>
#include <sstream>
#include <iterator>
#include <numeric>
#include <map>
#include <cstring>
#include <set>
#include <functional>
#include <iomanip>

using namespace std;

//#define DEBUG_ //!!提出時にコメントアウト!!
#ifdef DEBUG_
	#define dump(x)  cerr << #x << " = " << (x) << endl;
#else
	#define dump(x)  ;
#endif

#define equals(a,b) (fabs((a)-(b)) < EPS)
#define FOR(i,a,b) for(int i=(a);i<(b);++i)
#define REP(i,n)  FOR(i,0,n)
#define SZ(x) ((int)(x).size())
#define pb push_back
#define eb emplace_back

//#define int long long

typedef long long LL;
typedef vector<int> VI;
typedef vector<LL> VL;
typedef vector<VI> VVI;
typedef vector<string> VS;
typedef pair<int, int> PII;
typedef pair<LL, LL> PLL;

template <typename T>
std::string printVector(const std::vector<T> &data)
{
    std::stringstream ss;
    std::ostream_iterator<T> out_it(ss, ", ");
    ss << "[";
    std::copy(data.begin(), data.end() - 1, out_it);
    ss << data.back() << "]";
    return ss.str();
}

template <typename T>
void print_array(const T &ary, int size){
    REP(i,size){
        cout << ary[i] << " ";
    }
    cout << endl;
}

const int MOD = 1e9+7;
const LL LINF = 1001002003004005006ll;
const int INF = 1001001001;
const double EPS = (1e-10);

signed main(int argc, char const *argv[])
{
    cin.tie(0);
    ios::sync_with_stdio(false);
    cout << setprecision(12);

    int N; cin >> N;
    map<PII,vector<PII>> mp;
    vector<VI> par;
    REP(i,N){
        VI x(3);
        cin >> x[0] >> x[1] >> x[2];
        sort(x.begin(),x.end());
        par.eb(x);

        dump(x[0])

        // a bc
        if(int(mp[PII(x[1],x[2])].size()) <= 5){
            mp[PII(x[1],x[2])].eb(PII(x[0],i));
        }else{
            sort(mp[PII(x[1],x[2])].begin(),mp[PII(x[1],x[2])].end());
            auto p = min_element(mp[PII(x[1],x[2])].begin(),mp[PII(x[1],x[2])].end());
            if(*p < PII(x[0],i)){
                mp[PII(x[1],x[2])][0] = PII(x[0],i);
                dump(x[0])
            }
        }

        // b ac
        if(x[0] != x[1]){
          if(int(mp[PII(x[0],x[2])].size()) <= 5){
            mp[PII(x[0],x[2])].eb(PII(x[1],i));
          }else{
            sort(mp[PII(x[0],x[2])].begin(),mp[PII(x[0],x[2])].end());
            auto p = min_element(mp[PII(x[0],x[2])].begin(),mp[PII(x[0],x[2])].end());
            if(*p > PII(x[1],i)){
                mp[PII(x[0],x[2])][0] = PII(x[1],i);
            }

          }
        }
        // c ab
        if(x[1] != x[2]){
          if(int(mp[PII(x[0],x[1])].size()) <= 5){
            mp[PII(x[0],x[1])].eb(PII(x[2],i));
          }else{
            sort(mp[PII(x[0],x[1])].begin(),mp[PII(x[0],x[1])].end());
            auto p = min_element(mp[PII(x[0],x[1])].begin(),mp[PII(x[0],x[1])].end());
            if(*p > PII(x[2],i)){
                mp[PII(x[0],x[1])][0] = PII(x[2],i);
            }

          }
        }

    }
    VI ans;
    LL memo = -1;
    REP(i,N){
        if(par[i][0] > memo) {
            ans = {i+1};
            memo = par[i][0];
        }

        sort(mp[PII(par[i][1],par[i][2])].begin(),mp[PII(par[i][1],par[i][2])].end());
        auto it = mp[PII(par[i][1],par[i][2])].end();
        it--;
        dump(par[i][0])
        dump(it->first)
        if(it->second != i){
            if(min({0LL+it->first+par[i][0],0LL + par[i][1],0LL+par[i][2]}) > memo) {
                ans = {i+1,it->second+1};
                memo = min({0LL+it->first+par[i][0],0LL+par[i][1],0LL+par[i][2]});
            }
        }else{
            while(it != mp[PII(par[i][1],par[i][2])].begin()){

                it--;
                //if(it->first+par[i][0] > memo) ans = {i+1,it->second+1};
                if(min({0LL+it->first+par[i][0],0LL+par[i][1],0LL+par[i][2]}) > memo) {
                    ans = {i+1,it->second+1};
                    memo = min({0LL+it->first+par[i][0],0LL+par[i][1],0LL+par[i][2]});

                }
            }
        }
        //sort(mp[PII(par[i][0],par[i][2])].begin(),mp[PII(par[i][0],par[i][2])].end());
        //it = mp[PII(par[i][0],par[i][2])].end();
        //it--;
        //if(it->second != i){
        //    if(min({0LL+it->first+par[i][1],0LL+par[i][0],0LL+par[i][2]}) > memo) {
        //        ans = {i+1,it->second+1};
        //        memo = min({0LL+it->first+par[i][1],0LL+par[i][0],0LL+par[i][2]});
        //    }
        //}else{
        //    while(it != mp[PII(par[i][0],par[i][2])].begin()){

        //        it--;
        //        //if(it->first+par[i][0] > memo) ans = {i+1,it->second+1};
        //        if(min({0LL+it->first+par[i][1],0LL+par[i][0],0LL+par[i][2]}) > memo) {
        //            ans = {i+1,it->second+1};
        //            memo = min({0LL+it->first+par[i][1],0LL+par[i][0],0LL+par[i][2]});

        //        }
        //    }
        //}
        //sort(mp[PII(par[i][0],par[i][1])].begin(),mp[PII(par[i][0],par[i][1])].end());
        //it = mp[PII(par[i][0],par[i][1])].end();
        //it--;
        //if(it->second != i){
        //    if(min({0LL+it->first+par[i][2],0LL+par[i][0],0LL+par[i][1]}) > memo) {
        //        ans = {i+1,it->second+1};
        //        memo = min({0LL+it->first+par[i][2],0LL+par[i][0],0LL+par[i][1]});
        //    }
        //}else{
        //    while(it != mp[PII(par[i][0],par[i][1])].begin()){

        //        it--;
        //        //if(it->first+par[i][0] > memo) ans = {i+1,it->second+1};
        //        if(min({0LL+it->first+par[i][2],0LL+par[i][0],0LL+par[i][1]}) > memo) {
        //            ans = {i+1,it->second+1};
        //            memo = min({0LL+it->first+par[i][2],0LL+par[i][0],0LL+par[i][1]});

        //        }
        //    }
        //}

    }
    cout << int(ans.size()) << endl;
    int alen = ans.size();
    REP(i,alen){
        if(i != 0) cout << " ";
        cout << ans[i];
    }
    cout << endl;
    //if(ans[0] == 100000 && ans[1] == 6){
    //    REP(i,alen){
    //        cout << par[ans[i]-1][0] << " " << par[ans[i]-1][1] << " " << par[ans[i]-1][2] << endl;
    //    }
    //    cout << par[99998][0] << " " << par[99998][1] << " " << par[99998][2] << endl;

    //    cout << memo << endl;
    //    auto ite = (mp[PII(100000000,100000000)].end()-1);
    //    cout << ite->first << ite->second << endl;

    //}

}


#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <stack>
#include <queue>
#include <cmath>
#include <tuple>
#include <cstdio>
#include <bitset>
#include <sstream>
#include <iterator>
#include <numeric>
#include <map>
#include <cstring>
#include <set>
#include <functional>
#include <iomanip>

using namespace std;

//#define DEBUG_ //!!提出時にコメントアウト!!
#ifdef DEBUG_
	#define dump(x)  cerr << #x << " = " << (x) << endl;
#else
	#define dump(x)  ;
#endif

#define equals(a,b) (fabs((a)-(b)) < EPS)
#define FOR(i,a,b) for(int i=(a);i<(b);++i)
#define REP(i,n)  FOR(i,0,n)
#define SZ(x) ((int)(x).size())
#define pb push_back
#define eb emplace_back

//#define int long long

typedef long long LL;
typedef vector<int> VI;
typedef vector<LL> VL;
typedef vector<VI> VVI;
typedef vector<string> VS;
typedef pair<int, int> PII;
typedef pair<LL, LL> PLL;

template <typename T>
std::string printVector(const std::vector<T> &data)
{
    std::stringstream ss;
    std::ostream_iterator<T> out_it(ss, ", ");
    ss << "[";
    std::copy(data.begin(), data.end() - 1, out_it);
    ss << data.back() << "]";
    return ss.str();
}

template <typename T>
void print_array(const T &ary, int size){
    REP(i,size){
        cout << ary[i] << " ";
    }
    cout << endl;
}

const int MOD = 1e9+7;
const LL LINF = 1001002003004005006ll;
const int INF = 1001001001;
const double EPS = (1e-10);

signed main(int argc, char const *argv[])
{
    cin.tie(0);
    ios::sync_with_stdio(false);
    cout << setprecision(12);

    int N; cin >> N;
    map<PII,vector<PII>> mp;
    vector<VI> par;
    REP(i,N){
        VI x(3);
        cin >> x[0] >> x[1] >> x[2];
        sort(x.begin(),x.end());
        par.eb(x);

        // a bc
        if(int(mp[PII(x[1],x[2])].size()) <= 5){
            mp[PII(x[1],x[2])].eb(PII(x[0],i));
        }else{
            sort(mp[PII(x[1],x[2])].begin(),mp[PII(x[1],x[2])].end());
            auto p = min_element(mp[PII(x[1],x[2])].begin(),mp[PII(x[1],x[2])].end());
            if(*p > PII(x[0],i)){
                mp[PII(x[1],x[2])][0] = PII(x[0],i);
            }
        }

        // b ac
        if(x[0] != x[1]){
          if(int(mp[PII(x[0],x[2])].size()) <= 5){
            mp[PII(x[0],x[2])].eb(PII(x[1],i));
          }else{
            sort(mp[PII(x[0],x[2])].begin(),mp[PII(x[0],x[2])].end());
            auto p = min_element(mp[PII(x[0],x[2])].begin(),mp[PII(x[0],x[2])].end());
            if(*p > PII(x[1],i)){
                mp[PII(x[0],x[2])][0] = PII(x[1],i);
            }

          }
        }
        // c ab
        if(x[1] != x[2]){
          if(int(mp[PII(x[0],x[1])].size()) <= 5){
            mp[PII(x[0],x[1])].eb(PII(x[2],i));
          }else{
            sort(mp[PII(x[0],x[1])].begin(),mp[PII(x[0],x[1])].end());
            auto p = min_element(mp[PII(x[0],x[1])].begin(),mp[PII(x[0],x[1])].end());
            if(*p > PII(x[2],i)){
                mp[PII(x[0],x[1])][0] = PII(x[2],i);
            }

          }
        }

    }
    VI ans;
    int memo = -1;
    REP(i,N){
        if(par[i][0] > memo) {
            ans = {i+1};
            memo = par[i][0];
        }

        sort(mp[PII(par[i][1],par[i][2])].begin(),mp[PII(par[i][1],par[i][2])].end());
        auto it = mp[PII(par[i][1],par[i][2])].end();
        it--;
        if(it->second != i){
            if(min({0LL+it->first+par[i][0],0LL + par[i][1],0LL+par[i][2]}) > memo) {
                ans = {i+1,it->second+1};
                memo = min({0LL+it->first+par[i][0],0LL+par[i][1],0LL+par[i][2]});
            }
        }else{
            while(it != mp[PII(par[i][1],par[i][2])].begin()){

                it--;
                //if(it->first+par[i][0] > memo) ans = {i+1,it->second+1};
                if(min({0LL+it->first+par[i][0],0LL+par[i][1],0LL+par[i][2]}) > memo) {
                    ans = {i+1,it->second+1};
                    memo = min({0LL+it->first+par[i][0],0LL+par[i][1],0LL+par[i][2]});

                }
            }
        }
        sort(mp[PII(par[i][0],par[i][2])].begin(),mp[PII(par[i][0],par[i][2])].end());
        it = mp[PII(par[i][0],par[i][2])].end();
        it--;
        if(it->second != i){
            if(min({0LL+it->first+par[i][1],0LL+par[i][0],0LL+par[i][2]}) > memo) {
                ans = {i+1,it->second+1};
                memo = min({0LL+it->first+par[i][1],0LL+par[i][0],0LL+par[i][2]});
            }
        }else{
            while(it != mp[PII(par[i][0],par[i][2])].begin()){

                it--;
                //if(it->first+par[i][0] > memo) ans = {i+1,it->second+1};
                if(min({0LL+it->first+par[i][1],0LL+par[i][0],0LL+par[i][2]}) > memo) {
                    ans = {i+1,it->second+1};
                    memo = min({0LL+it->first+par[i][1],0LL+par[i][0],0LL+par[i][2]});

                }
            }
        }
        sort(mp[PII(par[i][0],par[i][1])].begin(),mp[PII(par[i][0],par[i][1])].end());
        it = mp[PII(par[i][0],par[i][1])].end();
        it--;
        if(it->second != i){
            if(min({0LL+it->first+par[i][2],0LL+par[i][0],0LL+par[i][1]}) > memo) {
                ans = {i+1,it->second+1};
                memo = min({0LL+it->first+par[i][2],0LL+par[i][0],0LL+par[i][1]});
            }
        }else{
            while(it != mp[PII(par[i][0],par[i][1])].begin()){

                it--;
                //if(it->first+par[i][0] > memo) ans = {i+1,it->second+1};
                if(min({0LL+it->first+par[i][2],0LL+par[i][0],0LL+par[i][1]}) > memo) {
                    ans = {i+1,it->second+1};
                    memo = min({0LL+it->first+par[i][2],0LL+par[i][0],0LL+par[i][1]});

                }
            }
        }

    }
    cout << int(ans.size()) << endl;
    int alen = ans.size();
    REP(i,alen){
        if(i != 0) cout << " ";
        cout << ans[i];
    }
    cout << endl;

}


#include<bits/stdc++.h>
#include<math.h>
#include<algorithm>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace std;
using namespace __gnu_pbds;
const double pi=3.141592653589;
long long int mod = 1000000007;
const long long int inf = 1e9;
const long long int inff = 9000000000000000000;
long double eps = 1e-9;
#define pry  cout<<"YES\n"
#define prn  cout<<"NO\n"
#define prm cout<<"-1\n"
#define nl cout<<"\n"
#define loop(i,a,b) for(int i=a;i<b;i+=1)
#define rloop(i,a,b) for(int i=a;i>=b;i-=1)
#define ll long long int
#define ld long double
#define pb push_back
#define pf push_front
#define popf pop_front
#define popb pop_back
#define ft first
#define sd second
#define pii pair<int,int>
#define pll pair<long long int, long long int>
#define mysort(a) sort(a.begin(),a.end())
#define myreverse(a) reverse(a.begin(),a.end())
#define mylb(a,val) lower_bound(a.begin(),a.end(),val)
#define myub(a,val) upper_bound(a.begin(),a.end(),val)
#define mem(a,vall) memset(a, vall, sizeof(a))
#define ordered_set tree< ll, null_type,less< ll >, rb_tree_tag,tree_order_statistics_node_update>
#define read1 for(int i=0; i<n; i++){cin>>arr[i];}
#define read2 for(int i=0; i<n; i++){ for(int j=0; j<m; j++) { cin>>arr[i][j]; } }
/*ll power(ll x, ll y, ll p)
{
    ll res = 1;

    x = x % p;
    while (y > 0)
    {
        if (y & 1)
            res = (res*x) % p;
        y = y>>1;
        x = (x*x) % p;
    }
    return res;
}
ll modInverse(ll n, ll p)
{
    return power(n, p-2, p);
}
ll ncr(ll n, ll r, ll p)
{
   if (r==0)
      return 1;

    ll fac[n+1];
    fac[0] = 1;
    for (ll i=1 ; i<=n; i++)
        fac[i] = fac[i-1]*i%p;

    return (fac[n]* modInverse(fac[r], p) % p *
            modInverse(fac[n-r], p) % p) % p;
}
ll log(ll a,ll b)
{
    if(a==1)
        return b;
    ll ans = 0;
    while(b)
    {
        ans++;
        b/=a;
    }
    return ans-1;
}*/

int main()
{

    ios_base::sync_with_stdio(false);
    cin.tie(0);cout.tie(0);
    int test=1;
    //freopen("galactic.in", "r", stdin);    // file open for input
    //freopen("output.txt", "w", stdout);   // file open for output
    //cin>>test;                                 // comment this when number of testcases = 1

    while(test--)
    {

        int n;
        cin>>n;
        ll a,b,c,ans=0,one=-1,two=-1;
        map< pll,set<pll> > mp;
        loop(i,0,n)
        {
            cin>>a>>b>>c;
            if( min({a,b,c}) > ans )
            {
                ans = min({a,b,c}) ;
                one = i+1;
            }

            mp[{min(a,b),max(a,b)}].insert({c,i+1});
            mp[{min(c,b),max(c,b)}].insert({a,i+1});
            mp[{min(a,c),max(a,c)}].insert({b,i+1});
        }

        map< pll,set<pll> >:: iterator it;
        it=mp.begin();
        set<pll>:: iterator it1;
        pll g,h;
        while(it!=mp.end())
        {
            h=it->first;
            if(it->second.size()<2){it++; continue;}
            it1=it->second.end();
            it1--;
            g=*it1;
            a=g.ft;
            it1--;
            g=*it1;
            a+=g.ft;
            if( ans < min({a,h.ft,h.sd}) )
            {
                ans=min({a,h.ft,h.sd});
                g=*it1;
                one=g.sd;
                it1++;
                g=*it1;
                two=g.sd;
            }
            it++;
        }

        if(two==-1)
        {
            cout<<1;
            nl;
            cout<<one;
        }
        else
        {
            cout<<2;
            nl;
            cout<<one<<" "<<two;
        }

    }

    return 0;

}


#include<bits/stdc++.h>
#include<math.h>
#include<algorithm>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace std;
using namespace __gnu_pbds;
const double pi=3.141592653589;
long long int mod = 1000000007;
const long long int inf = 1e9;
const long long int inff = 9000000000000000000;
long double eps = 1e-9;
#define pry  cout<<"YES\n"
#define prn  cout<<"NO\n"
#define prm cout<<"-1\n"
#define nl cout<<"\n"
#define loop(i,a,b) for(int i=a;i<b;i+=1)
#define rloop(i,a,b) for(int i=a;i>=b;i-=1)
#define ll long long int
#define ld long double
#define pb push_back
#define pf push_front
#define popf pop_front
#define popb pop_back
#define ft first
#define sd second
#define pii pair<int,int>
#define pll pair<long long int, long long int>
#define mysort(a) sort(a.begin(),a.end())
#define myreverse(a) reverse(a.begin(),a.end())
#define mylb(a,val) lower_bound(a.begin(),a.end(),val)
#define myub(a,val) upper_bound(a.begin(),a.end(),val)
#define mem(a,vall) memset(a, vall, sizeof(a))
#define ordered_set tree< ll, null_type,less< ll >, rb_tree_tag,tree_order_statistics_node_update>
#define read1 for(int i=0; i<n; i++){cin>>arr[i];}
#define read2 for(int i=0; i<n; i++){ for(int j=0; j<m; j++) { cin>>arr[i][j]; } }
/*ll power(ll x, ll y, ll p)
{
    ll res = 1;

    x = x % p;
    while (y > 0)
    {
        if (y & 1)
            res = (res*x) % p;
        y = y>>1;
        x = (x*x) % p;
    }
    return res;
}
ll modInverse(ll n, ll p)
{
    return power(n, p-2, p);
}
ll ncr(ll n, ll r, ll p)
{
   if (r==0)
      return 1;

    ll fac[n+1];
    fac[0] = 1;
    for (ll i=1 ; i<=n; i++)
        fac[i] = fac[i-1]*i%p;

    return (fac[n]* modInverse(fac[r], p) % p *
            modInverse(fac[n-r], p) % p) % p;
}
ll log(ll a,ll b)
{
    if(a==1)
        return b;
    ll ans = 0;
    while(b)
    {
        ans++;
        b/=a;
    }
    return ans-1;
}*/

int main()
{

    ios_base::sync_with_stdio(false);
    cin.tie(0);cout.tie(0);
    int test=1;
    //freopen("galactic.in", "r", stdin);    // file open for input
    //freopen("output.txt", "w", stdout);   // file open for output
    //cin>>test;                                 // comment this when number of testcases = 1

    while(test--)
    {

        int n;
        cin>>n;
        ll a,b,c,d;
        map< pll, multiset<ll> > mp;
        ll aa[n];
        ll bb[n];
        ll cc[n];
        loop(i,0,n)
        {
            cin>>a>>b>>c;
            d=min({a,b,c});

            mp[{a,b}].insert(c);
            mp[{a,c}].insert(b);
            mp[{b,c}].insert(a);
            aa[i]=a;
            bb[i]=b;
            cc[i]=c;
        }

        map< pll, multiset<ll> >:: iterator it;
        it=mp.begin();
        multiset<ll>:: iterator it1;
        vector<ll> v;
        ll ans=-inff;
        while(it!=mp.end())
        {
            it1=it->second.end();
            it1--;
            d=0;
            d+=*it1;

            if(it1!=it->second.begin())
            {
                it1--;
                d+=*it1;
            }
            if( min({it->first.ft,it->first.sd,d}) > ans )
            {
                v.clear();
                v.pb(it->first.ft);
                v.pb(it->first.sd);
                it1=it->second.end();
                it1--;
                v.pb(*it1);
                if(it1!=it->second.begin())
                {
                    it1--;
                    v.pb(*it1);
                }
                ans=min({it->first.ft,it->first.sd,d});
            }

            it++;
        }

        vector<int> finalans;
        loop(i,0,n)
        {
            int x=0,y=0,z=0;
            int used[v.size()];
            mem(used,0);
            loop(j,0,v.size())
            {
                if(used[j]==0 && aa[i]==v[j])
                {
                    used[j]=1;
                    x=1;
                    break;
                }
            }
            loop(j,0,v.size())
            {
                if(used[j]==0 && bb[i]==v[j])
                {
                    used[j]=1;
                    y=1;
                    break;
                }
            }
            loop(j,0,v.size())
            {
                if(used[j]==0 && cc[i]==v[j])
                {
                    used[j]=1;
                    z=1;
                    break;
                }
            }

            if(x==1 && y==1 && z==1){finalans.pb(i+1);}
        }

        int sizz=finalans.size();
        cout<<min(sizz,2);
        nl;

        loop(i,0,min(sizz,2))
        {
            cout<<finalans[i]<<" ";
        }

    }

    return 0;

}


#include<bits/stdc++.h>
#include<math.h>
#include<algorithm>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace std;
using namespace __gnu_pbds;
const double pi=3.141592653589;
long long int mod = 1000000007;
const long long int inf = 1e9;
const long long int inff = 9000000000000000000;
long double eps = 1e-9;
#define pry  cout<<"YES\n"
#define prn  cout<<"NO\n"
#define prm cout<<"-1\n"
#define nl cout<<"\n"
#define loop(i,a,b) for(int i=a;i<b;i+=1)
#define rloop(i,a,b) for(int i=a;i>=b;i-=1)
#define ll long long int
#define ld long double
#define pb push_back
#define pf push_front
#define popf pop_front
#define popb pop_back
#define ft first
#define sd second
#define pii pair<int,int>
#define pll pair<long long int, long long int>
#define mysort(a) sort(a.begin(),a.end())
#define myreverse(a) reverse(a.begin(),a.end())
#define mylb(a,val) lower_bound(a.begin(),a.end(),val)
#define myub(a,val) upper_bound(a.begin(),a.end(),val)
#define mem(a,vall) memset(a, vall, sizeof(a))
#define ordered_set tree< ll, null_type,less< ll >, rb_tree_tag,tree_order_statistics_node_update>
#define read1 for(int i=0; i<n; i++){cin>>arr[i];}
#define read2 for(int i=0; i<n; i++){ for(int j=0; j<m; j++) { cin>>arr[i][j]; } }
/*ll power(ll x, ll y, ll p)
{
    ll res = 1;

    x = x % p;
    while (y > 0)
    {
        if (y & 1)
            res = (res*x) % p;
        y = y>>1;
        x = (x*x) % p;
    }
    return res;
}
ll modInverse(ll n, ll p)
{
    return power(n, p-2, p);
}
ll ncr(ll n, ll r, ll p)
{
   if (r==0)
      return 1;

    ll fac[n+1];
    fac[0] = 1;
    for (ll i=1 ; i<=n; i++)
        fac[i] = fac[i-1]*i%p;

    return (fac[n]* modInverse(fac[r], p) % p *
            modInverse(fac[n-r], p) % p) % p;
}
ll log(ll a,ll b)
{
    if(a==1)
        return b;
    ll ans = 0;
    while(b)
    {
        ans++;
        b/=a;
    }
    return ans-1;
}*/

int main()
{

    ios_base::sync_with_stdio(false);
    cin.tie(0);cout.tie(0);
    int test=1;
    //freopen("galactic.in", "r", stdin);    // file open for input
    //freopen("output.txt", "w", stdout);   // file open for output
    //cin>>test;                                 // comment this when number of testcases = 1

    while(test--)
    {

        int n;
        cin>>n;
        ll a,b,c,d;
        map< pll, multiset<ll> > mp;
        ll aa[n];
        ll bb[n];
        ll cc[n];
        loop(i,0,n)
        {
            cin>>a>>b>>c;
            d=min({a,b,c});
            if(a==b && a==c)
            {
                mp[{a,b}].insert(c);
            }
            else if(a==b)
            {
                mp[{a,b}].insert(c);
                mp[{a,c}].insert(b);
            }
            else if(b==c)
            {
                mp[{a,b}].insert(c);
                mp[{b,c}].insert(a);
            }
            else if(a==c)
            {
                mp[{a,b}].insert(c);
                mp[{a,c}].insert(b);
            }
            else{
            mp[{a,b}].insert(c);
            mp[{a,c}].insert(b);
            mp[{b,c}].insert(a);}
            aa[i]=a;
            bb[i]=b;
            cc[i]=c;
        }

        map< pll, multiset<ll> >:: iterator it;
        it=mp.begin();
        multiset<ll>:: iterator it1;
        vector<ll> v;
        ll ans=-inff;
        while(it!=mp.end())
        {
            it1=it->second.end();
            it1--;
            d=0;
            d+=*it1;

            if(it1!=it->second.begin())
            {
                it1--;
                d+=*it1;
            }
            if( min({it->first.ft,it->first.sd,d}) > ans )
            {
                v.clear();
                v.pb(it->first.ft);
                v.pb(it->first.sd);
                it1=it->second.end();
                it1--;
                v.pb(*it1);
                if(it1!=it->second.begin())
                {
                    it1--;
                    v.pb(*it1);
                }
                ans=min({it->first.ft,it->first.sd,d});
            }

            it++;
        }

        vector<int> finalans;
        loop(i,0,n)
        {
            int x=0,y=0,z=0;
            int used[v.size()];
            mem(used,0);
            loop(j,0,v.size())
            {
                if(used[j]==0 && aa[i]==v[j])
                {
                    used[j]=1;
                    x=1;
                    break;
                }
            }
            loop(j,0,v.size())
            {
                if(used[j]==0 && bb[i]==v[j])
                {
                    used[j]=1;
                    y=1;
                    break;
                }
            }
            loop(j,0,v.size())
            {
                if(used[j]==0 && cc[i]==v[j])
                {
                    used[j]=1;
                    z=1;
                    break;
                }
            }

            if(x==1 && y==1 && z==1){finalans.pb(i+1);}
        }

        int sizz=finalans.size();
        cout<<min(sizz,2);
        nl;

        loop(i,0,min(sizz,2))
        {
            cout<<finalans[i]<<" ";
        }

    }

    return 0;

}


#pragma GCC optimize ("O3")
#pragma GCC target ("sse4")
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef long double ld;
typedef vector<int> vi;
typedef pair<int, int> pi;
#define debug(x) cerr << #x << ": " << x << endl
#define debug2(x, y) debug(x), debug(y)
#define repn(i, a, b) for(int i = (int)(a); i < (int)(b); i++)
#define rep(i, a) for(int i = 0; i < (int)(a); i++)
#define all(v) v.begin(), v.end()
#define mp make_pair
#define pb push_back
#define lb lower_bound
#define ub upper_bound
#define fi first
#define se second
#define sq(x) ((x) * (x))
const int mxN = 1e5 + 5;

template<class T> T gcd(T a, T b){ return ((b == 0) ? a : gcd(b, a % b)); }

ll a[mxN][3];

void pr(__int128 x){
	string s = "";
	while(x){
		s += (char)((x % 10) + '0');
		x /= 10;
	}
	reverse(all(s));
	cout << s << endl;
}

int main(){
	ios_base::sync_with_stdio(false);
	cin.tie(0);
	//freopen("input.in", "r", stdin);
	//freopen("output.out", "w", stdout);
	int n;
	cin >> n;
	rep(i, n) rep(j, 3) cin >> a[i][j];
	map<pair<ll, ll>, pair<ll, ll>> m;
	ll bst = 0;
	vi cur = {};
	rep(i, n){
		ll cr = min({a[i][0], a[i][1], a[i][2]});
		if(cr > bst){
			bst = cr;
			cur = {i + 1};
		}
		rep(j, 3) rep(k, 3) if(j != k){
			int p = -1;
			rep(l, 3) if(l != j && l != k) p = l; //the extra
			pair<ll, ll> nw = m[mp(a[i][j], a[i][k])];
			if(nw.fi){
				ll bg = min({a[i][j], a[i][k], a[i][p] + nw.fi});
				if(bg > bst){
					bst = bg;
					cur = {nw.se + 1, i + 1};
				}
			}
		}
		rep(j, 3) rep(k, 3) if(j != k){
			int p = -1;
			rep(l, 3) if(l != j && l != k) p = l; //the extra
			if(a[i][p] > m[mp(a[i][j], a[i][k])].fi){
				m[mp(a[i][j], a[i][k])] = mp(a[i][p], i);
			}
			if(a[i][p] > m[mp(a[i][k], a[i][j])].fi){
				m[mp(a[i][k], a[i][j])] = mp(a[i][p], i);
			}
		}
	}
	cout << cur.size() << endl;
	for(int x : cur) cout << x << " ";
	cout << endl;
	return 0;
}
/*
Things to look out for:
	- Integer overflows
	- Array bounds
	- Special cases
Be careful!
*/


#pragma GCC optimize ("O3")
#pragma GCC target ("sse4")
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef long double ld;
typedef vector<int> vi;
typedef pair<int, int> pi;
#define debug(x) cerr << #x << ": " << x << endl
#define debug2(x, y) debug(x), debug(y)
#define repn(i, a, b) for(int i = (int)(a); i < (int)(b); i++)
#define rep(i, a) for(int i = 0; i < (int)(a); i++)
#define all(v) v.begin(), v.end()
#define mp make_pair
#define pb push_back
#define lb lower_bound
#define ub upper_bound
#define fi first
#define se second
#define sq(x) ((x) * (x))
const int mxN = 1e5 + 5;

template<class T> T gcd(T a, T b){ return ((b == 0) ? a : gcd(b, a % b)); }

ll a[mxN][3];

int main(){
	ios_base::sync_with_stdio(false);
	cin.tie(0);
	//freopen("input.in", "r", stdin);
	//freopen("output.out", "w", stdout);
	int n;
	cin >> n;
	rep(i, n) rep(j, 3) cin >> a[i][j];
	map<pair<ll, ll>, pair<ll, ll>> m;
	__int128 bst = 0;
	vi cur = {};
	rep(i, n){
		__int128 cr = (__int128)((__int128)(a[i][0] * a[i][1]) * a[i][2]);
		assert(cr >= 0);
		if(cr > bst){
			bst = cr;
			cur = {i + 1};
		}
		rep(j, 3) rep(k, 3) if(j != k){
			int p = -1;
			rep(l, 3) if(l != j && l != k) p = l; //the extra
			pair<ll, ll> nw = m[mp(a[i][j], a[i][k])];
			if(nw.fi){
				__int128 bg = (__int128)((__int128)(a[i][j] * a[i][k]) * (__int128)(a[i][p] + nw.fi));
				assert(bg >= 0);
				if(bg > bst){
					bst = bg;
					cur = {nw.se + 1, i + 1};
				}
			}
		}
		rep(j, 3) rep(k, 3) if(j != k){
			int p = -1;
			rep(l, 3) if(l != j && l != k) p = l; //the extra
			if(a[i][p] > m[mp(a[i][j], a[i][k])].fi){
				m[mp(a[i][j], a[i][k])] = mp(a[i][p], i);
			}
			if(a[i][p] > m[mp(a[i][k], a[i][j])].fi){
				m[mp(a[i][k], a[i][j])] = mp(a[i][p], i);
			}
		}
	}
	cout << cur.size() << endl;
	for(int x : cur) cout << x << " ";
	cout << endl;
	return 0;
}
/*
Things to look out for:
	- Integer overflows
	- Array bounds
	- Special cases
Be careful!
*/


#pragma GCC optimize ("O3")
#pragma GCC target ("sse4")
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef long double ld;
typedef vector<int> vi;
typedef pair<int, int> pi;
#define debug(x) cerr << #x << ": " << x << endl
#define debug2(x, y) debug(x), debug(y)
#define repn(i, a, b) for(int i = (int)(a); i < (int)(b); i++)
#define rep(i, a) for(int i = 0; i < (int)(a); i++)
#define all(v) v.begin(), v.end()
#define mp make_pair
#define pb push_back
#define lb lower_bound
#define ub upper_bound
#define fi first
#define se second
#define sq(x) ((x) * (x))
const int mxN = 1e5 + 5;

template<class T> T gcd(T a, T b){ return ((b == 0) ? a : gcd(b, a % b)); }

ll a[mxN][3];

int main(){
	ios_base::sync_with_stdio(false);
	cin.tie(0);
	//freopen("input.in", "r", stdin);
	//freopen("output.out", "w", stdout);
	int n;
	cin >> n;
	rep(i, n) rep(j, 3) cin >> a[i][j];
	map<pair<ll, ll>, pair<ll, ll>> m;
	__int128 bst = 0;
	vi cur = {};
	rep(i, n){
		__int128 cr = (__int128)((__int128)(a[i][0] * a[i][1]) * a[i][2]);
		if(cr > bst){
			bst = cr;
			cur = {i + 1};
		}
		rep(j, 3) repn(k, j + 1, 3){
			int p = -1;
			rep(l, 3) if(l != j && l != k) p = l; //the extra
			pi nw = m[mp(a[i][j], a[i][k])];
			if(nw.fi){
				__int128 bg = (__int128)((__int128)(a[i][j] * a[i][k]) * (__int128)(a[i][p] + nw.fi));
				if(bg > bst){
					bst = bg;
					cur = {nw.se + 1, i + 1};
				}
			}
		}
		rep(j, 3) repn(k, j + 1, 3){
			int p = -1;
			rep(l, 3) if(l != j && l != k) p = l; //the extra
			m[mp(a[i][j], a[i][k])] = mp(max(m[mp(a[i][j], a[i][k])].fi, a[i][p]), i);
			m[mp(a[i][k], a[i][j])] = mp(max(m[mp(a[i][k], a[i][j])].fi, a[i][p]), i);
		}
	}
	cout << cur.size() << endl;
	for(int x : cur) cout << x << " ";
	cout << endl;
	return 0;
}
/*
Things to look out for:
	- Integer overflows
	- Array bounds
	- Special cases
Be careful!
*/


#pragma GCC optimize ("O3")
#pragma GCC target ("sse4")
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef long double ld;
typedef vector<int> vi;
typedef pair<int, int> pi;
#define debug(x) cerr << #x << ": " << x << endl
#define debug2(x, y) debug(x), debug(y)
#define repn(i, a, b) for(int i = (int)(a); i < (int)(b); i++)
#define rep(i, a) for(int i = 0; i < (int)(a); i++)
#define all(v) v.begin(), v.end()
#define mp make_pair
#define pb push_back
#define lb lower_bound
#define ub upper_bound
#define fi first
#define se second
#define sq(x) ((x) * (x))
const int mxN = 1e5 + 5;

template<class T> T gcd(T a, T b){ return ((b == 0) ? a : gcd(b, a % b)); }

ll a[mxN][3];

int main(){
	ios_base::sync_with_stdio(false);
	cin.tie(0);
	//freopen("input.in", "r", stdin);
	//freopen("output.out", "w", stdout);
	int n;
	cin >> n;
	rep(i, n) rep(j, 3) cin >> a[i][j];
	map<pair<ll, ll>, pair<ll, ll>> m;
	ll bst = 0;
	vi cur = {};
	rep(i, n){
		ll cr = min({a[i][0], a[i][1], a[i][2]});
		if(cr > bst){
			bst = cr;
			cur = {i + 1};
		}
		rep(j, 3) rep(k, 3) if(j != k){
			int p = -1;
			rep(l, 3) if(l != j && l != k) p = l; //the extra
			pair<ll, ll> nw = m[mp(a[i][j], a[i][k])];
			if(nw.fi){
				ll bg = min({a[i][j], a[i][k], a[i][p] + nw.fi});
				if(bg > bst){
					bst = bg;
					cur = {nw.se + 1, i + 1};
				}
			}
		}
		rep(j, 3) rep(k, 3) if(j != k){
			int p = -1;
			rep(l, 3) if(l != j && l != k) p = l; //the extra
			if(a[i][p] > m[mp(a[i][j], a[i][k])].fi){
				m[mp(a[i][j], a[i][k])] = mp(a[i][p], i);
			}
			if(a[i][p] > m[mp(a[i][k], a[i][j])].fi){
				m[mp(a[i][k], a[i][j])] = mp(a[i][p], i);
			}
		}
	}
	cout << cur.size() << endl;
	for(int x : cur) cout << x << " ";
	cout << endl;
	return 0;
}
/*
Things to look out for:
	- Integer overflows
	- Array bounds
	- Special cases
Be careful!
*/


#pragma GCC optimize ("O3")
#pragma GCC target ("sse4")
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef long double ld;
typedef vector<int> vi;
typedef pair<int, int> pi;
#define debug(x) cerr << #x << ": " << x << endl
#define debug2(x, y) debug(x), debug(y)
#define repn(i, a, b) for(int i = (int)(a); i < (int)(b); i++)
#define rep(i, a) for(int i = 0; i < (int)(a); i++)
#define all(v) v.begin(), v.end()
#define mp make_pair
#define pb push_back
#define lb lower_bound
#define ub upper_bound
#define fi first
#define se second
#define sq(x) ((x) * (x))
const int mxN = 1e5 + 5;

template<class T> T gcd(T a, T b){ return ((b == 0) ? a : gcd(b, a % b)); }

ll a[mxN][3];

int main(){
	ios_base::sync_with_stdio(false);
	cin.tie(0);
	//freopen("input.in", "r", stdin);
	//freopen("output.out", "w", stdout);
	int n;
	cin >> n;
	rep(i, n) rep(j, 3) cin >> a[i][j];
	map<pair<ll, ll>, pair<ll, ll>> m;
	__int128 bst = 0;
	vi cur = {};
	rep(i, n){
		__int128 cr = (__int128)((__int128)(a[i][0] * a[i][1]) * a[i][2]);
		if(cr > bst){
			bst = cr;
			cur = {i + 1};
		}
		rep(j, 3) repn(k, j + 1, 3){
			int p = -1;
			rep(l, 3) if(l != j && l != k) p = l; //the extra
			pi nw = m[mp(a[i][j], a[i][k])];
			if(nw.fi){
				__int128 bg = (__int128)((__int128)(a[i][j] * a[i][k]) * (__int128)(a[i][p] + nw.fi));
				if(bg > bst){
					bst = bg;
					cur = {nw.se + 1, i + 1};
				}
			}
		}
		rep(j, 3) repn(k, j + 1, 3){
			int p = -1;
			rep(l, 3) if(l != j && l != k) p = l; //the extra
			if(a[i][p] > m[mp(a[i][j], a[i][k])].fi){
				m[mp(a[i][j], a[i][k])] = mp(max(m[mp(a[i][j], a[i][k])].fi, a[i][p]), i);
			}
			if(a[i][p] > m[mp(a[i][k], a[i][j])].fi){
				m[mp(a[i][k], a[i][j])] = mp(max(m[mp(a[i][k], a[i][j])].fi, a[i][p]), i);
			}
		}
	}
	cout << cur.size() << endl;
	for(int x : cur) cout << x << " ";
	cout << endl;
	return 0;
}
/*
Things to look out for:
	- Integer overflows
	- Array bounds
	- Special cases
Be careful!
*/


#pragma GCC optimize ("O3")
#pragma GCC target ("sse4")
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef long double ld;
typedef vector<int> vi;
typedef pair<int, int> pi;
#define debug(x) cerr << #x << ": " << x << endl
#define debug2(x, y) debug(x), debug(y)
#define repn(i, a, b) for(int i = (int)(a); i < (int)(b); i++)
#define rep(i, a) for(int i = 0; i < (int)(a); i++)
#define all(v) v.begin(), v.end()
#define mp make_pair
#define pb push_back
#define lb lower_bound
#define ub upper_bound
#define fi first
#define se second
#define sq(x) ((x) * (x))
const int mxN = 1e5 + 5;

template<class T> T gcd(T a, T b){ return ((b == 0) ? a : gcd(b, a % b)); }

ll a[mxN][3];

int main(){
	ios_base::sync_with_stdio(false);
	cin.tie(0);
	//freopen("input.in", "r", stdin);
	//freopen("output.out", "w", stdout);
	int n;
	cin >> n;
	rep(i, n) rep(j, 3) cin >> a[i][j];
	map<pair<ll, ll>, pair<ll, ll>> m;
	__int128 bst = 0;
	vi cur = {};
	rep(i, n){
		__int128 cr = (__int128)((__int128)(a[i][0] * a[i][1]) * a[i][2]);
		if(cr > bst){
			bst = cr;
			cur = {i + 1};
		}
		rep(j, 3) rep(k, 3) if(j != k){
			int p = -1;
			rep(l, 3) if(l != j && l != k) p = l; //the extra
			pair<ll, ll> nw = m[mp(a[i][j], a[i][k])];
			if(nw.fi){
				__int128 bg = (__int128)((__int128)(a[i][j] * a[i][k]) * (__int128)(a[i][p] + nw.fi));
				if(bg > bst){
					bst = bg;
					cur = {nw.se + 1, i + 1};
				}
			}
		}
		rep(j, 3) rep(k, 3) if(j != k){
			int p = -1;
			rep(l, 3) if(l != j && l != k) p = l; //the extra
			if(a[i][p] > m[mp(a[i][j], a[i][k])].fi){
				m[mp(a[i][j], a[i][k])] = mp(a[i][p], i);
			}
			if(a[i][p] > m[mp(a[i][k], a[i][j])].fi){
				m[mp(a[i][k], a[i][j])] = mp(a[i][p], i);
			}
		}
	}
	cout << cur.size() << endl;
	for(int x : cur) cout << x << " ";
	cout << endl;
	return 0;
}
/*
Things to look out for:
	- Integer overflows
	- Array bounds
	- Special cases
Be careful!
*/


#include <bits/stdc++.h>
using namespace std;
#define ll long long int

inline long long inp()
{
    long long n = 0;
    char c = _getchar_nolock();
    while(c<'0'|| c>'9') c = _getchar_nolock();
    while(c>='0'&&c<='9')
    {
        n =(n<<3)+(n<<1)+c - '0';
        c = _getchar_nolock();
    }
    return n;
}

int main()
{
    ll n, temp=0, fl=0, ifl=0, sl=0, isl=0, single=0, single_index=0, multi=0;
    map<pair<ll, ll>, set< pair<ll, ll> > > m;
    vector<ll> v, multiindex;

    n = inp();
    // INPUT
    for(ll i=1; i<=n; i++)
    {
        for(int i=0; i<3; i++)
        {
            temp = inp();
            v.push_back(temp);
        }
        sort(v.begin(), v.end());

        //CREATING MAP OF PAIRS
        m[make_pair(v[0], v[1])].insert(make_pair(v[2], i));
        m[make_pair(v[1], v[2])].insert(make_pair(v[0], i));
        m[make_pair(v[0], v[2])].insert(make_pair(v[1], i));

        if(v[0] > single)
        {
            single = v[0];
            single_index = i;
        }
        v.clear();
    }

    for(auto it=m.rbegin(); it!=m.rend(); it++)
    {

        if(it->first.first <= single || it->first.first < multi)
        {
            if(single>=multi)
            {
                cout << 1 << endl;
                cout << single_index;
                break;
            }
            else
            {
                cout << 2 << endl;
                cout << multiindex[0] << " " << multiindex[1];
                break;
            }
        }
        else if(it->second.size() > 1)
        {
            auto jit = it->second.end()--;
            fl = jit->first;
            ifl = jit->second;
            jit--;
            sl = jit->first;
            isl = jit->second;

            temp = fl + sl;
            if(temp < (it->first.first) )
            {
                multi = temp;
            }
            else
            {
                multi = it->first.first;
            }

            multiindex.clear();
            multiindex.push_back(ifl);
            multiindex.push_back(isl);
            sort(multiindex.begin(), multiindex.end());
        }
    }
}


#include <bits/stdc++.h>
using namespace std;
#define ll long long int

inline long long inp()
{
    long long n = 0;
    char c = _getchar_nolock();
    while(c<'0'|| c>'9') c = _getchar_nolock();
    while(c>='0'&&c<='9')
    {
        n =(n<<3)+(n<<1)+c - '0';
        c = _getchar_nolock();
    }
    return n;
}

int main()
{
    ll n, temp, fl, ifl, sl, isl, single=0, single_index=0, multi=0;
    map<pair<ll, ll>, set< pair<ll, ll> > > m;
    vector<ll> v, multiindex;

    n = inp();
    // INPUT
    for(ll i=1; i<=n; i++)
    {
        for(int i=0; i<3; i++)
        {
            temp = inp();
            v.push_back(temp);
        }
        sort(v.begin(), v.end());

        //CREATING MAP OF PAIRS
        m[make_pair(v[0], v[1])].insert(make_pair(v[2], i));
        m[make_pair(v[1], v[2])].insert(make_pair(v[0], i));
        m[make_pair(v[0], v[2])].insert(make_pair(v[1], i));

        if(v[0] > single)
        {
            single = v[0];
            single_index = i;
        }
        v.clear();
    }

    for(auto it=m.rbegin(); it!=m.rend(); it++)
    {

        if(it->first.first <= single || it->first.first <= multi)
        {
            if(single>=multi)
            {
                cout << 1 << endl;
                cout << single_index;
                break;
            }
            else
            {
                cout << 2 << endl;
                cout << multiindex[0] << " " << multiindex[1];
                break;
            }
        }
        else
        {
            auto jit = max_element(it->second.begin(), it->second.end());
            fl = jit->first;
            ifl = jit->second;
            it->second.erase(jit);
            jit = max_element(it->second.begin(), it->second.end());
            sl = jit->first;
            isl = jit->second;

            temp = fl + sl;
            if(temp < (it->first.first) )
            {
                multi = temp;
            }
            else
            {
                multi = it->first.first;
            }

            multiindex.clear();
            multiindex.push_back(ifl);
            multiindex.push_back(isl);
            sort(multiindex.begin(), multiindex.end());
        }
    }
}


#include <bits/stdc++.h>
using namespace std;
#define ll long long int

inline long long inp()
{
    long long n = 0;
    char c = _getchar_nolock();
    while(c<'0'|| c>'9') c = _getchar_nolock();
    while(c>='0'&&c<='9')
    {
        n =(n<<3)+(n<<1)+c - '0';
        c = _getchar_nolock();
    }
    return n;
}

int main()
{
    ll n, temp=0, fl=0, ifl=0, sl=0, isl=0, single=0, single_index=0, multi=0;
    map<pair<ll, ll>, set< pair<ll, ll> > > m;
    vector<ll> v, multiindex;

    n = inp();
    // INPUT
    for(ll i=1; i<=n; i++)
    {
        for(int i=0; i<3; i++)
        {
            temp = inp();
            v.push_back(temp);
        }
        sort(v.begin(), v.end());

        //CREATING MAP OF PAIRS
        m[make_pair(v[0], v[1])].insert(make_pair(v[2], i));
        m[make_pair(v[1], v[2])].insert(make_pair(v[0], i));
        m[make_pair(v[0], v[2])].insert(make_pair(v[1], i));

        if(v[0] > single)
        {
            single = v[0];
            single_index = i;
        }
        v.clear();
    }

    for(auto it=m.rbegin(); it!=m.rend(); it++)
    {

        if(it->first.first <= single || it->first.first <= multi)
        {
            if(single>=multi)
            {
                cout << 1 << endl;
                cout << single_index;
                break;
            }
            else
            {
                cout << 2 << endl;
                cout << multiindex[0] << " " << multiindex[1];
                break;
            }
        }
        else if(it->second.size() > 1)
        {
            auto jit = it->second.end();
            jit--;
            fl = jit->first;
            ifl = jit->second;
            jit--;
            sl = jit->first;
            isl = jit->second;

            temp = fl + sl;
            if(temp < (it->first.first) )
            {
                multi = temp;
            }
            else
            {
                multi = it->first.first;
            }

            multiindex.clear();
            multiindex.push_back(ifl);
            multiindex.push_back(isl);
            sort(multiindex.begin(), multiindex.end());
        }
    }
}


#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <vector>
using namespace std;
const int maxn=110000;
int n;
struct Tinit{int f,u;}A[maxn];

struct Tcxx{
    int A,B;
    Tcxx(int _A=0,int _B=0){A=_A,B=_B;}
    inline bool operator<(const Tcxx &b)const{
        return A!=b.A?A<b.A:B<b.B;
    }
    inline Tcxx operator +(const Tcxx &b)const{
        return Tcxx(A+b.A,B+b.B);
    }
};

struct Talt{
    int tot;
    struct Tsqy{
        int s;Tsqy *l;
        inline void set(Tsqy *_l,int _s){l=_l,s=_s;}
    }*pos[maxn],buf[maxn];
    inline void add(int a,int b){
        buf[++tot].set(pos[a],b),pos[a]=buf+tot;
    }
}alt;

namespace Ninit{
    void init(){
        int i;
        scanf("%d",&n);
        for(i=1;i<=n;++i){
            scanf("%d%d",&A[i].f,&A[i].u);
            --A[i].u,alt.add(A[i].f,i);
        }
    }
}

namespace Nsolve{
    Tcxx ans;vector<Tcxx> B;
    bool U[maxn];
    namespace Ntree{
        Tcxx F[maxn][2];int G[maxn];
        vector<Tcxx> E;
        void dfs(int x,int rt){
            Talt::Tsqy *p;Tcxx ret;
            U[x]=true,F[x][0]=F[x][1]=Tcxx();
            for(p=alt.pos[x];p;p=p->l)if(p->s!=rt){
                dfs(p->s,rt);
                F[x][1]=F[x][1]+max(F[p->s][0],F[p->s][1]);
                ret=F[x][0]+F[p->s][0]+Tcxx(1,A[x].u^A[p->s].u);
                if(F[x][1]<ret)F[x][1]=ret,G[x]=p->s;
                F[x][0]=F[x][0]+max(F[p->s][0],F[p->s][1]);
            }
        }
        void constrc(int x,int c,int rt){
            Talt::Tsqy *p;
            for(p=alt.pos[x];p;p=p->l)if(p->s!=rt){
                if(!c || p->s!=G[x])
                    constrc(p->s,F[p->s][0]<F[p->s][1]?1:0,rt);
                else E.push_back(Tcxx(x,p->s)),constrc(p->s,0,rt);
            }
        }
        void solve(int x){
            Tcxx Fc;int i;
            for(;!U[x];x=A[x].f)U[x]=true;
            for(i=0;i<2;++i,x=A[x].f){
                dfs(x,x);
                if(Fc<F[x][1]){
                    Fc=F[x][1];
                    E.clear(),constrc(x,1,x);
                }
            }
            ans=ans+Fc,B.insert(B.end(),E.begin(),E.end());
        }
    }
    void solve(){
        int i;vector<Tcxx>::iterator p;
        for(i=1;i<=n;++i)
            if(!U[i])Ntree::solve(i);
        printf("%d %d\n",ans.A,ans.B);
        for(p=B.begin();p!=B.end();++p)
            printf("%d %d\n",p->A,p->B);
    }
}

int main(){
    Ninit::init();
    Nsolve::solve();
    return 0;
}


#ifdef ONLINE_JUDGE
#pragma comment(linker, "/STACK:16777216")
#endif

#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <vector>
#include <map>
#include <set>
#include <bitset>
#include <queue>
#include <stack>
#include <sstream>
#include <cstring>
#include <numeric>
#include <ctime>

#define re return
#define fi first
#define se second
#define mp make_pair
#define pb push_back
#define all(x) (x).begin(), (x).end()
#define sz(x) ((int) (x).size())
#define rep(i, n) for (int i = 0; i < (n); i++)
#define rrep(i, n) for (int i = (n) - 1; i >= 0; i--)
#define y0 y32479
#define y1 y95874
#define fill(x, y) memset(x, y, sizeof(x))
#define sqr(x) ((x) * (x))
#define prev prev239
#define next next239
#define hash hash239
#define rank rank239

using namespace std;

typedef vector<int> vi;
typedef vector<vi> vvi;
typedef pair<int, int> ii;
typedef vector<ii> vii;
typedef vector<string> vs;
typedef long long ll;
typedef double D;
typedef long double LD;

template<class T> T abs(T x) {return x > 0 ? x : -x;}

int n;
int m;

int next[100000], t[100000];
vi prev[100000];
int color[100000], was[100000], col[100000];
vii res;
ii ans1[100000], ans2[100000];
int next2[100000];

queue<int> q;

void parse(int x) {
    was[x] = 1;
    col[next[x]]--;
    if (col[next[x]] == 0)
        q.push(next[x]);
}

ii operator + (ii a, ii b) {
    re mp(a.fi + b.fi, a.se + b.se);
}

ii operator - (ii a, ii b) {
    re mp(a.fi - b.fi, a.se - b.se);
}

ii table[2][100001];
int o[2][100001];

ii get(int x, int y) {
    re mp(1, t[x] != t[y]);
}

void calc(int x) {
    ii sum0 = mp(0, 0);
    ii sum1 = mp(0, 0);
    rep(i, sz(prev[x])) {
        int u = prev[x][i];
        if (was[u] == 0)
            continue;
        calc(u);
        sum0 = sum0 + ans1[u];
        sum1 = sum1 + ans1[u];
    }

    ii a2 = sum1;
    next2[x] = -1;
    rep(i, sz(prev[x])) {
        int u = prev[x][i];
        if (was[u] == 0)
            continue;
        ii tmp = sum1 + ans2[u] - ans1[u] + get(x, u);
        if (tmp > a2) {
            a2 = tmp;
            next2[x] = u;
        }
    }

    ans1[x] = a2;
    ans2[x] = sum0;
}

void add(int x, int f) {
    rep(i, sz(prev[x])) {
        int u = prev[x][i];
        if (was[u] == 0)
            continue;
        if (u == next2[x] && f == 1) {
            add(u, 0);
            res.pb(mp(x, u));
        }
        else
            add(u, 1);
    }
}

ii getans(int x) {
    vi mas;
    int cur = x;
    do {
        mas.pb(cur);
        color[cur] = 1;
        cur = next[cur];
    }
    while (next[cur] != x);
    mas.pb(cur);
    color[cur] = 1;

    int n = sz(mas);
    rep(i, n)
    calc(mas[i]);

    mas.pb(mas[0]);
    rep(l, 2) {
        table[n][n] = mp(0, 0);
    }

    rep(l, 2)
    rrep(i, n) {
        ii &ans = table[l][i];
        if (i == n - 1) {
            if (l == 0) {
                ans = get(mas[i], mas[0]) + ans2[mas[i]];
                o[l][i] = 1;
            }
            else {
                ans = ans1[mas[i]];
                o[l][i] = 0;
            }
        }
        else {
            if (i == 0 && l == 0) {
                ans = table[l][i + 1];
                o[l][i] = 0;
                continue;
            }
            ans = ans1[mas[i]] + table[l][i + 1];
            o[l][i] = 0;
            if (l != 0 || i != n - 2) {
                ii tmp = get(mas[i], mas[i + 1]) + ans2[mas[i]] + ans2[mas[i + 1]] + table[l][i + 2];
                if (ans < tmp) {
                    ans = tmp;
                    o[l][i] = 1;
                }
            }
        }
    }

    int cl = 0;
    if (table[1][0] > table[0][0])
        cl = 1;
    int cp = 0;
    while (cp < n) {
        if (o[cl][cp]) {
            res.pb(mp(mas[cp], mas[cp + 1]));
            add(mas[cp], 0);
            add(mas[cp + 1], 0);
            cp += 2;
        }
        else {
            add(mas[cp], 1);
            cp++;
        }
    }

    re max(table[1][0], table[0][0]);
}

int main() {
#ifndef ONLINE_JUDGE
    freopen("input.txt", "r", stdin);
    //freopen("output.txt", "w", stdout);
#endif

    cin >> n;
    rep(i, n) {
        int a, b;
        scanf("%d%d", &a, &b);
        a--;
        b--;
        col[a]++;
        prev[a].pb(i);
        next[i] = a;
        t[i] = b;
    }

    rep(i, n)
    if (col[i] == 0)
        q.push(i);

    while (!q.empty()) {
        parse(q.front());
        q.pop();
    }

    ii ans = mp(0, 0);
    fill(color, -1);
    rep(i, n)
    if (!was[i] && color[i] == -1) {
        ans = ans + getans(i);
    }

    cout << ans.fi << ' ' << ans.se << endl;
    rep(i, sz(res)) {
        cout << res[i].fi + 1 << ' ' << res[i].se + 1 << endl;
    }

    re 0;
}


#ifdef ONLINE_JUDGE
#pragma comment(linker, "/STACK:16777216")
#endif

#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <vector>
#include <map>
#include <set>
#include <bitset>
#include <queue>
#include <stack>
#include <sstream>
#include <cstring>
#include <numeric>
#include <ctime>

#define re return
#define fi first
#define se second
#define mp make_pair
#define pb push_back
#define all(x) (x).begin(), (x).end()
#define sz(x) ((int) (x).size())
#define rep(i, n) for (int i = 0; i < (n); i++)
#define rrep(i, n) for (int i = (n) - 1; i >= 0; i--)
#define y0 y32479
#define y1 y95874
#define fill(x, y) memset(x, y, sizeof(x))
#define sqr(x) ((x) * (x))
#define prev prev239
#define next next239
#define hash hash239
#define rank rank239

using namespace std;

typedef vector<int> vi;
typedef vector<vi> vvi;
typedef pair<int, int> ii;
typedef vector<ii> vii;
typedef vector<string> vs;
typedef long long ll;
typedef double D;
typedef long double LD;

template<class T> T abs(T x) {return x > 0 ? x : -x;}

int n;
int m;

int next[100000], t[100000];
vi prev[100000];
int color[100000], was[100000], col[100000];
vii res;
ii ans1[100000], ans2[100000];
int next2[100000];

queue<int> q;

void parse(int x) {
    was[x] = 1;
    col[next[x]]--;
    if (col[next[x]] == 0)
        q.push(next[x]);
}

ii operator + (ii a, ii b) {
    re mp(a.fi + b.fi, a.se + b.se);
}

ii operator - (ii a, ii b) {
    re mp(a.fi - b.fi, a.se - b.se);
}

ii table[2][100001];
int o[2][100001];

ii get(int x, int y) {
    re mp(1, t[x] != t[y]);
}

void calc(int x) {
    ii sum0 = mp(0, 0);
    ii sum1 = mp(0, 0);
    rep(i, sz(prev[x])) {
        int u = prev[x][i];
        if (was[u] == 0)
            continue;
        calc(u);
        sum0 = sum0 + ans1[u];
        sum1 = sum1 + ans1[u];
    }

    ii a2 = sum1;
    next2[x] = -1;
    rep(i, sz(prev[x])) {
        int u = prev[x][i];
        if (was[u] == 0)
            continue;
        ii tmp = sum1 + ans2[u] - ans1[u] + get(x, u);
        if (tmp > a2) {
            a2 = tmp;
            next2[x] = u;
        }
    }

    ans1[x] = a2;
    ans2[x] = sum0;
}

void add(int x, int f) {
    //cout << "   " << x << ' ' << f << endl;
    rep(i, sz(prev[x])) {
        int u = prev[x][i];
        if (was[u] == 0)
            continue;
        if (u == next2[x] && f == 1) {
            add(u, 0);
            res.pb(mp(x, u));
        }
        else
            add(u, 1);
    }
}

ii getans(int x) {
    vi mas;
    int cur = x;
    do {
        mas.pb(cur);
        color[cur] = 1;
        cur = next[cur];
    }
    while (next[cur] != x);
    mas.pb(cur);
    color[cur] = 1;

    int n = sz(mas);
    rep(i, n)
    calc(mas[i]);

    mas.pb(mas[0]);
    rep(l, 2) {
        table[l][n] = mp(0, 0);
    }

    rep(l, 2)
    rrep(i, n) {
        ii &ans = table[l][i];
        if (i == n - 1) {
            if (l == 0) {
                ans = get(mas[i], mas[0]) + ans2[mas[i]];
                o[l][i] = 1;
            }
            else {
                ans = ans1[mas[i]];
                o[l][i] = 0;
            }
        }
        else {
            if (i == 0 && l == 0) {
                ans = table[l][i + 1] + ans2[mas[0]];
                o[l][i] = 0;
                continue;
            }
            ans = ans1[mas[i]] + table[l][i + 1];
            o[l][i] = 0;
            if (l != 0 || i != n - 2) {
                ii tmp = get(mas[i], mas[i + 1]) + ans2[mas[i]] + ans2[mas[i + 1]] + table[l][i + 2];
                if (ans < tmp) {
                    ans = tmp;
                    o[l][i] = 1;
                }
            }
        }
    }

    int cl = 0;
    if (table[1][0] > table[0][0])
        cl = 1;
    int cp = 0;
    while (cp < n) {
        if (o[cl][cp]) {
            res.pb(mp(mas[cp], mas[cp + 1]));
            add(mas[cp], 0);
            if (cp + 1 < n)
            add(mas[cp + 1], 0);
            cp += 2;
        }
        else {
            if (cl == 0 && cp == 0)
                add(mas[cp], 0);
            else
            add(mas[cp], 1);
            cp++;
        }
    }

    re max(table[1][0], table[0][0]);
}

int main() {
#ifndef ONLINE_JUDGE
    freopen("input.txt", "r", stdin);
    //freopen("output.txt", "w", stdout);
#endif

    cin >> n;
    rep(i, n) {
        int a, b;
        scanf("%d%d", &a, &b);
        a--;
        b--;
        col[a]++;
        prev[a].pb(i);
        next[i] = a;
        t[i] = b;
    }

    rep(i, n)
    if (col[i] == 0)
        q.push(i);

    while (!q.empty()) {
        parse(q.front());
        q.pop();
    }

    ii ans = mp(0, 0);
    fill(color, -1);
    rep(i, n)
    if (!was[i] && color[i] == -1) {
        ans = ans + getans(i);
    }

    cout << ans.fi << ' ' << ans.se << endl;
    rep(i, sz(res)) {
        cout << res[i].fi + 1 << ' ' << res[i].se + 1 << endl;
    }

    re 0;
}


#ifdef ONLINE_JUDGE
#pragma comment(linker, "/STACK:16777216")
#endif

#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <vector>
#include <map>
#include <set>
#include <bitset>
#include <queue>
#include <stack>
#include <sstream>
#include <cstring>
#include <numeric>
#include <ctime>

#define re return
#define fi first
#define se second
#define mp make_pair
#define pb push_back
#define all(x) (x).begin(), (x).end()
#define sz(x) ((int) (x).size())
#define rep(i, n) for (int i = 0; i < (n); i++)
#define rrep(i, n) for (int i = (n) - 1; i >= 0; i--)
#define y0 y32479
#define y1 y95874
#define fill(x, y) memset(x, y, sizeof(x))
#define sqr(x) ((x) * (x))
#define prev prev239
#define next next239
#define hash hash239
#define rank rank239

using namespace std;

typedef vector<int> vi;
typedef vector<vi> vvi;
typedef pair<int, int> ii;
typedef vector<ii> vii;
typedef vector<string> vs;
typedef long long ll;
typedef double D;
typedef long double LD;

template<class T> T abs(T x) {return x > 0 ? x : -x;}

int n;
int m;

int next[100000], t[100000];
vi prev[100000];
int color[100000], was[100000], col[100000];
vii res;
ii ans1[100000], ans2[100000];
int next2[100000];

queue<int> q;

void parse(int x) {
    was[x] = 1;
    col[next[x]]--;
    if (col[next[x]] == 0)
        q.push(next[x]);
}

ii operator + (ii a, ii b) {
    re mp(a.fi + b.fi, a.se + b.se);
}

ii operator - (ii a, ii b) {
    re mp(a.fi - b.fi, a.se - b.se);
}

ii table[2][100001];
int o[2][100001];

ii get(int x, int y) {
    re mp(1, t[x] != t[y]);
}

void calc(int x) {
    ii sum0 = mp(0, 0);
    ii sum1 = mp(0, 0);
    rep(i, sz(prev[x])) {
        int u = prev[x][i];
        if (was[u] == 0)
            continue;
        calc(u);
        sum0 = sum0 + ans1[u];
        sum1 = sum1 + ans1[u];
    }

    ii a2 = sum1;
    next2[x] = -1;
    rep(i, sz(prev[x])) {
        int u = prev[x][i];
        if (was[u] == 0)
            continue;
        ii tmp = sum1 + ans2[u] - ans1[u] + get(x, u);
        if (tmp > a2) {
            a2 = tmp;
            next2[x] = u;
        }
    }

    ans1[x] = a2;
    ans2[x] = sum0;
}

void add(int x, int f) {
    //cout << "   " << x << ' ' << f << endl;
    rep(i, sz(prev[x])) {
        int u = prev[x][i];
        if (was[u] == 0)
            continue;
        if (u == next2[x] && f == 1) {
            add(u, 0);
            res.pb(mp(x, u));
        }
        else
            add(u, 1);
    }
}

ii getans(int x) {
    vi mas;
    int cur = x;
    do {
        mas.pb(cur);
        color[cur] = 1;
        cur = next[cur];
    }
    while (next[cur] != x);
    mas.pb(cur);
    color[cur] = 1;

    int n = sz(mas);
    rep(i, n)
    calc(mas[i]);

    mas.pb(mas[0]);
    rep(l, 2) {
        table[n][n] = mp(0, 0);
    }

    rep(l, 2)
    rrep(i, n) {
        ii &ans = table[l][i];
        if (i == n - 1) {
            if (l == 0) {
                ans = get(mas[i], mas[0]) + ans2[mas[i]];
                o[l][i] = 1;
            }
            else {
                ans = ans1[mas[i]];
                o[l][i] = 0;
            }
        }
        else {
            if (i == 0 && l == 0) {
                ans = table[l][i + 1] + ans2[mas[0]];
                o[l][i] = 0;
                continue;
            }
            ans = ans1[mas[i]] + table[l][i + 1];
            o[l][i] = 0;
            if (l != 0 || i != n - 2) {
                ii tmp = get(mas[i], mas[i + 1]) + ans2[mas[i]] + ans2[mas[i + 1]] + table[l][i + 2];
                if (ans < tmp) {
                    ans = tmp;
                    o[l][i] = 1;
                }
            }
        }
    }

    int cl = 0;
    if (table[1][0] > table[0][0])
        cl = 1;
    int cp = 0;
    while (cp < n) {
        if (o[cl][cp]) {
            res.pb(mp(mas[cp], mas[cp + 1]));
            add(mas[cp], 0);
            if (cp + 1 < n)
            add(mas[cp + 1], 0);
            cp += 2;
        }
        else {
            if (cl == 0 && cp == 0)
                add(mas[cp], 0);
            else
            add(mas[cp], 1);
            cp++;
        }
    }

    re max(table[1][0], table[0][0]);
}

int main() {
#ifndef ONLINE_JUDGE
    freopen("input.txt", "r", stdin);
    //freopen("output.txt", "w", stdout);
#endif

    cin >> n;
    rep(i, n) {
        int a, b;
        scanf("%d%d", &a, &b);
        a--;
        b--;
        col[a]++;
        prev[a].pb(i);
        next[i] = a;
        t[i] = b;
    }

    rep(i, n)
    if (col[i] == 0)
        q.push(i);

    while (!q.empty()) {
        parse(q.front());
        q.pop();
    }

    ii ans = mp(0, 0);
    fill(color, -1);
    rep(i, n)
    if (!was[i] && color[i] == -1) {
        ans = ans + getans(i);
    }

    cout << ans.fi << ' ' << ans.se << endl;
    rep(i, sz(res)) {
        cout << res[i].fi + 1 << ' ' << res[i].se + 1 << endl;
    }

    re 0;
}


#ifdef ONLINE_JUDGE
#pragma comment(linker, "/STACK:16777216")
#endif

#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <vector>
#include <map>
#include <set>
#include <bitset>
#include <queue>
#include <stack>
#include <sstream>
#include <cstring>
#include <numeric>
#include <ctime>

#define re return
#define fi first
#define se second
#define mp make_pair
#define pb push_back
#define all(x) (x).begin(), (x).end()
#define sz(x) ((int) (x).size())
#define rep(i, n) for (int i = 0; i < (n); i++)
#define rrep(i, n) for (int i = (n) - 1; i >= 0; i--)
#define y0 y32479
#define y1 y95874
#define fill(x, y) memset(x, y, sizeof(x))
#define sqr(x) ((x) * (x))
#define prev prev239
#define next next239
#define hash hash239
#define rank rank239

using namespace std;

typedef vector<int> vi;
typedef vector<vi> vvi;
typedef pair<int, int> ii;
typedef vector<ii> vii;
typedef vector<string> vs;
typedef long long ll;
typedef double D;
typedef long double LD;

template<class T> T abs(T x) {return x > 0 ? x : -x;}

int n;
int m;

int next[100000], t[100000];
vi prev[100000];
int color[100000], was[100000], col[100000];
vii res;
ii ans1[100000], ans2[100000];
int next2[100000];

queue<int> q;

void parse(int x) {
    was[x] = 1;
    col[next[x]]--;
    if (col[next[x]] == 0)
        q.push(next[x]);
}

ii operator + (ii a, ii b) {
    re mp(a.fi + b.fi, a.se + b.se);
}

ii operator - (ii a, ii b) {
    re mp(a.fi - b.fi, a.se - b.se);
}

ii table[2][100001];
int o[2][100001];

ii get(int x, int y) {
    re mp(1, t[x] != t[y]);
}

void calc(int x) {
    ii sum0 = mp(0, 0);
    ii sum1 = mp(0, 0);
    rep(i, sz(prev[x])) {
        int u = prev[x][i];
        if (was[u] == 0)
            continue;
        calc(u);
        sum0 = sum0 + ans1[u];
        sum1 = sum1 + ans1[u];
    }

    ii a2 = sum1;
    next2[x] = -1;
    rep(i, sz(prev[x])) {
        int u = prev[x][i];
        if (was[u] == 0)
            continue;
        ii tmp = sum1 + ans2[u] - ans1[u] + get(x, u);
        if (tmp > a2) {
            a2 = tmp;
            next2[x] = u;
        }
    }

    ans1[x] = a2;
    ans2[x] = sum0;
}

void add(int x, int f) {
    rep(i, sz(prev[x])) {
        int u = prev[x][i];
        if (was[u] == 0)
            continue;
        if (u == next2[x] && f == 1) {
            add(u, 0);
            res.pb(mp(x, u));
        }
        else
            add(u, 1);
    }
}

ii getans(int x) {
    vi mas;
    int cur = x;
    do {
        mas.pb(cur);
        color[cur] = 1;
        cur = next[cur];
    }
    while (next[cur] != x);
    mas.pb(cur);
    color[cur] = 1;

    int n = sz(mas);
    rep(i, n)
    calc(mas[i]);

    mas.pb(mas[0]);
    rep(l, 2) {
        table[n][n] = mp(0, 0);
    }

    rep(l, 2)
    rrep(i, n) {
        ii &ans = table[l][i];
        if (i == n - 1) {
            if (l == 0) {
                ans = get(mas[i], mas[0]) + ans2[mas[i]];
                o[l][i] = 1;
            }
            else {
                ans = ans1[mas[i]];
                o[l][i] = 0;
            }
        }
        else {
            if (i == 0 && l == 0) {
                ans = table[l][i + 1] + ans2[mas[0]];
                o[l][i] = 0;
                continue;
            }
            ans = ans1[mas[i]] + table[l][i + 1];
            o[l][i] = 0;
            if (l != 0 || i != n - 2) {
                ii tmp = get(mas[i], mas[i + 1]) + ans2[mas[i]] + ans2[mas[i + 1]] + table[l][i + 2];
                if (ans < tmp) {
                    ans = tmp;
                    o[l][i] = 1;
                }
            }
        }
    }

    int cl = 0;
    if (table[1][0] > table[0][0])
        cl = 1;
    int cp = 0;
    while (cp < n) {
        if (o[cl][cp]) {
            res.pb(mp(mas[cp], mas[cp + 1]));
            add(mas[cp], 0);
            add(mas[cp + 1], 0);
            cp += 2;
        }
        else {
            add(mas[cp], 1);
            cp++;
        }
    }

    re max(table[1][0], table[0][0]);
}

int main() {
#ifndef ONLINE_JUDGE
    freopen("input.txt", "r", stdin);
    //freopen("output.txt", "w", stdout);
#endif

    cin >> n;
    rep(i, n) {
        int a, b;
        scanf("%d%d", &a, &b);
        a--;
        b--;
        col[a]++;
        prev[a].pb(i);
        next[i] = a;
        t[i] = b;
    }

    rep(i, n)
    if (col[i] == 0)
        q.push(i);

    while (!q.empty()) {
        parse(q.front());
        q.pop();
    }

    ii ans = mp(0, 0);
    fill(color, -1);
    rep(i, n)
    if (!was[i] && color[i] == -1) {
        ans = ans + getans(i);
    }

    cout << ans.fi << ' ' << ans.se << endl;
    rep(i, sz(res)) {
        cout << res[i].fi + 1 << ' ' << res[i].se + 1 << endl;
    }

    re 0;
}


#ifdef ONLINE_JUDGE
#pragma comment(linker, "/STACK:16777216")
#endif

#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <vector>
#include <map>
#include <set>
#include <bitset>
#include <queue>
#include <stack>
#include <sstream>
#include <cstring>
#include <numeric>
#include <ctime>

#define re return
#define fi first
#define se second
#define mp make_pair
#define pb push_back
#define all(x) (x).begin(), (x).end()
#define sz(x) ((int) (x).size())
#define rep(i, n) for (int i = 0; i < (n); i++)
#define rrep(i, n) for (int i = (n) - 1; i >= 0; i--)
#define y0 y32479
#define y1 y95874
#define fill(x, y) memset(x, y, sizeof(x))
#define sqr(x) ((x) * (x))
#define prev prev239
#define next next239
#define hash hash239
#define rank rank239

using namespace std;

typedef vector<int> vi;
typedef vector<vi> vvi;
typedef pair<int, int> ii;
typedef vector<ii> vii;
typedef vector<string> vs;
typedef long long ll;
typedef double D;
typedef long double LD;

template<class T> T abs(T x) {return x > 0 ? x : -x;}

int n;
int m;

int next[100000], t[100000];
vi prev[100000];
int color[100000], was[100000], col[100000];
vii res;
ii ans1[100000], ans2[100000];
int next2[100000];

queue<int> q;

void parse(int x) {
    was[x] = 1;
    col[next[x]]--;
    if (col[next[x]] == 0)
        q.push(next[x]);
}

ii operator + (ii a, ii b) {
    re mp(a.fi + b.fi, a.se + b.se);
}

ii operator - (ii a, ii b) {
    re mp(a.fi - b.fi, a.se - b.se);
}

ii table[2][100001];
int o[2][100001];

ii get(int x, int y) {
    re mp(1, t[x] != t[y]);
}

void calc(int x) {
    ii sum0 = mp(0, 0);
    ii sum1 = mp(0, 0);
    rep(i, sz(prev[x])) {
        int u = prev[x][i];
        if (was[u] == 0)
            continue;
        calc(u);
        sum0 = sum0 + ans1[u];
        sum1 = sum1 + ans1[u];
    }

    ii a2 = sum1;
    next2[x] = -1;
    rep(i, sz(prev[x])) {
        int u = prev[x][i];
        if (was[u] == 0)
            continue;
        ii tmp = sum1 + ans2[u] - ans1[u] + get(x, u);
        if (tmp > a2) {
            a2 = tmp;
            next2[x] = u;
        }
    }

    ans1[x] = a2;
    ans2[x] = sum0;
}

void add(int x, int f) {
    //cout << "   " << x << ' ' << f << endl;
    rep(i, sz(prev[x])) {
        int u = prev[x][i];
        if (was[u] == 0)
            continue;
        if (u == next2[x] && f == 1) {
            add(u, 0);
            res.pb(mp(x, u));
        }
        else
            add(u, 1);
    }
}

ii getans(int x) {
    vi mas;
    int cur = x;
    do {
        mas.pb(cur);
        color[cur] = 1;
        cur = next[cur];
    }
    while (next[cur] != x);
    mas.pb(cur);
    color[cur] = 1;

    int n = sz(mas);
    rep(i, n)
    calc(mas[i]);

    mas.pb(mas[0]);
    rep(l, 2) {
        table[n][n] = mp(0, 0);
    }

    rep(l, 2)
    rrep(i, n) {
        ii &ans = table[l][i];
        if (i == n - 1) {
            if (l == 0) {
                ans = get(mas[i], mas[0]) + ans2[mas[i]];
                o[l][i] = 1;
            }
            else {
                ans = ans1[mas[i]];
                o[l][i] = 0;
            }
        }
        else {
            if (i == 0 && l == 0) {
                ans = table[l][i + 1] + ans2[mas[0]];
                o[l][i] = 0;
                continue;
            }
            ans = ans1[mas[i]] + table[l][i + 1];
            o[l][i] = 0;
            if (l != 0 || i != n - 2) {
                ii tmp = get(mas[i], mas[i + 1]) + ans2[mas[i]] + ans2[mas[i + 1]] + table[l][i + 2];
                if (ans < tmp) {
                    ans = tmp;
                    o[l][i] = 1;
                }
            }
        }
    }

    int cl = 0;
    if (table[1][0] > table[0][0])
        cl = 1;
    int cp = 0;
    while (cp < n) {
        if (o[cl][cp]) {
            res.pb(mp(mas[cp], mas[cp + 1]));
            add(mas[cp], 0);
            if (cp + 1 < n)
            add(mas[cp + 1], 0);
            cp += 2;
        }
        else {
            add(mas[cp], 1);
            cp++;
        }
    }

    re max(table[1][0], table[0][0]);
}

int main() {
#ifndef ONLINE_JUDGE
    freopen("input.txt", "r", stdin);
    //freopen("output.txt", "w", stdout);
#endif

    cin >> n;
    rep(i, n) {
        int a, b;
        scanf("%d%d", &a, &b);
        a--;
        b--;
        col[a]++;
        prev[a].pb(i);
        next[i] = a;
        t[i] = b;
    }

    rep(i, n)
    if (col[i] == 0)
        q.push(i);

    while (!q.empty()) {
        parse(q.front());
        q.pop();
    }

    ii ans = mp(0, 0);
    fill(color, -1);
    rep(i, n)
    if (!was[i] && color[i] == -1) {
        ans = ans + getans(i);
    }

    cout << ans.fi << ' ' << ans.se << endl;
    rep(i, sz(res)) {
        cout << res[i].fi + 1 << ' ' << res[i].se + 1 << endl;
    }

    re 0;
}