#include<bits/stdc++.h>

using namespace std;

typedef struct node_{
    public:
        queue<int> next;//次の添字(0始まりに変換している)
        int visited;
        int k;//出次数
        int u;//頂点番号
        int d;//発見時刻
        int f;//完了時刻
        node_(){};
}* node;

vector<node> readGraph(int n){
    vector<node> graph;
    for(int i = 0; i < n; i++){
        int u;
        int k;
        scanf("%d %d", &u, &k);
        node nd = new node_;
        nd -> k = k;
        nd -> u = u;
        nd -> visited = 0;
        for(int j = 0; j < k; j++){
            int v;
            scanf("%d", &v);
            v--;//0始まりに
            nd -> next.push(v);
        }
        graph.push_back(nd);
    }
    return graph;
}

void depthFirstSearch(vector<node> graph, int n){
    stack<int> st;
    int cnt = 0;//時刻
    for(int i = 0; i < n; i++){
        if(graph[i] -> visited == 1){
            
        }else{
            st.push(i);
            cnt++;
            graph[i] -> d = cnt;
            graph[i] -> visited = 1;
            while(st.empty() != 1){
                node nd = graph[st.top()];
                if(nd -> next.empty() == 1){
                    cnt++;
                    nd -> f = cnt;
                    st.pop();
                }else{
                    node nx = graph[nd -> next.front()];
                    if(nx -> visited == 1){
                        nd -> next.pop();
                    }else{
                        cnt++;
                        nx -> d = cnt;
                        nx -> visited = 1;
                        st.push(nd -> next.front());
                        nd -> next.pop();
                    }
                }
                /*
                if(graph[st.top()] -> next.empty() == 1){//訪れた点のnextがない//nextがemptyだとvisitedにならない
                    cnt++;
                    graph[st.top()] -> f = cnt;
                    st.pop();
                }else if(graph[graph[st.top()] -> next.front()] -> visited == 1){
                    graph[st.top()] -> next.pop();
                }else{
                    cnt++;
                    graph[graph[st.top()] -> next.front()] -> d = cnt;
                    graph[graph[st.top()] -> next.front()] -> visited = 1;
                    st.push(graph[st.top()] -> next.front());
                    graph[st.top()] -> next.pop();
                }
                */
            }
        }
    }
}

void printTestGraph(vector<node> graph, int n){
    for(int i = 0; i < n; i++){
        node nd = graph[i];
        printf("node[%d] u = %d k = %d\n", i, nd -> u, nd -> k);
        for(int j = 0; j < nd -> k; j++){
            printf("%d ", nd -> next.front());
            nd -> next.pop();
        }
        printf("\n");
    }
}

void printResult(vector<node> graph, int n){
    for(int i = 0; i < n; i++){
        node nd = graph[i];
        printf("%d %d %d\n", nd -> u, nd -> d, nd -> f);
    }
}

int main(){
    //printf("start\n");
    int n;
    scanf("%d", &n);
    vector<node> graph = readGraph(n);
    //printf("readGraph() end\n");
    //printTestGraph(graph, n);//ここまでうまくいってる
    depthFirstSearch(graph, n);
    //printf("depthFirstSearch() end\n");
    printResult(graph, n);
    return 0;
}


Measured memory_bytes: 3304