#include <stdio.h> 
#include <stdlib.h>

// disjoint set data structure
int* rank; int* parent;

// initialisation function 
void djset(int n) { 
	rank = (int*)malloc((n+1)*sizeof(int));
	parent = (int*)malloc((n+1)*sizeof(int));
    for (int i = 0; i <= n; i++){ 
		parent[i] = i; 
        rank[i] = 0; 
	}
} 

// finding the set of a node
int find(int x) { 
	if (parent[x] != x) { 
        parent[x] = find(parent[x]); 
    } 
	return parent[x]; 
}

// union function
void merge(int x, int y){ 
	int xset = find(x); 
	int yset = find(y); 

	if (xset == yset) 
		return; 

	if (rank[xset] < rank[yset]) parent[xset] = yset; 
	else if (rank[xset] > rank[yset]) parent[yset] = xset;
	else{ 
		parent[yset] = xset; 
		rank[xset] = rank[xset] + 1; 
	} 
} 

// linked list data structure
typedef struct node{
    int vertex, wt;
    struct node* next;
}node;

node* create(int vertex, int wt) {
    node* newnode = (node*)malloc(sizeof(node));
    newnode->vertex = vertex;
    newnode->wt = wt;
    newnode->next = NULL;
    return newnode;
}

// parameters are passed as &list[i], vertex, wt
void insert(node** head, int vertex, int wt) {
    node* newnode = create(vertex, wt);
    newnode->next = *head; *head = newnode;
}

//     node* n_th = list[i];
//     while(n_th != NULL){
//         printf("%d %d ", n_th->vertex, n_th->wt);
//         n_th = n_th->next;
//     }

// edge data structure
typedef struct {
    int u;
    int v;
    int wgt;
}e;

void func(e* edges, node** list, int n, int tot){
    int ctr = 0;
    for(int i=1; i<=n; i++){
        node* curr = list[i];
        while(curr != NULL){
            if ((curr->vertex) > i){
                edges[ctr].u = i;
                edges[ctr].v = (curr->vertex);
                edges[ctr].wgt = (curr->wt);
                ctr++;
            }
            curr = curr->next;
        }
    }
}

void sort(e* edges, int tot) {
    for (int i = 0; i < tot - 1; i++) {
        int min_idx = i;
        for (int j = i + 1; j < tot; j++) {
            if (edges[j].wgt < edges[min_idx].wgt) {
                min_idx = j;
            }
        }
        int temp_u = edges[min_idx].u;
        int temp_v = edges[min_idx].v;
        int temp_wgt = edges[min_idx].wgt;
        edges[min_idx].u = edges[i].u;
        edges[min_idx].v = edges[i].v;
        edges[min_idx].wgt = edges[i].wgt;
        edges[i].u = temp_u;
        edges[i].v = temp_v;
        edges[i].wgt = temp_wgt;
    }
}

int main(){
    // Disjoint set union
    int flag;
    scanf("%d ", &flag);
    int n = 0;

    if (flag == 0){
        int q;
        scanf("%d %d", &n, &q);

        djset(n);

        while(q--){
            int a, x, y;
            scanf("%d %d %d", &a, &x, &y);
            if (a == 0) merge(x, y);
            else{
                if (find(x) == find(y)) printf("1 ");
                else printf("0 ");
            }
        }
    }
    else{
        scanf("%d", &n);

        // linked list input
        node** list = (node*)malloc((n+1) * sizeof(node));

        for (int i = 0; i <= n; i++) {
            list[i] = NULL;
        }
        int tot = 0;
        int a, weight = -1;
        for(int i=1; i<=n; i++){
            a = 0;
            while(a != -1){
                scanf("%d", &a);
                if(a != -1){
                    scanf("%d", &weight);
                    insert(&list[i], a+1, weight);
                    tot++;
                }
            }
        }
        tot = tot / 2;
        e* edges = (e*)malloc(tot*sizeof(e));
        func(edges, list, n, tot);
        sort(edges, tot);
        djset(n);
        int mst = 0;
        for(int i=0; i<tot; i++){
            if (find(edges[i].u) != find(edges[i].v)){ 
                merge(edges[i].u, edges[i].v);
                mst += edges[i].wgt;
            }
        }
        printf("%d ", mst);

    }
	return 0; 
}