#include <cstdio>

using namespace std;

const int maxN=20;
const int maxP=50;
const int maxV=maxN*maxP;

struct edge {
     int w;
     edge *next;
     edge(int W=0,edge *NXT=0):w(W),next(NXT) {}
};

edge *adj[maxV];
edge edgs[2*maxV];
int eCnt;
int sg[maxV];

inline void AddEdge(int a,int b) {
     edgs[eCnt]=edge(b,adj[a]);
     adj[a]=&edgs[eCnt++];
}
int CountSG(int v,int prv=-1) {
     bool reachable[maxP+2]={0};
     for(edge *e=adj[v];e;e=e->next)
	  if(e->w!=prv) 
	       reachable[CountSG(e->w,v)]=true;
     for(sg[v]=0;reachable[sg[v]];sg[v]++);
     return sg[v];
}
int main() {
     int firstv[maxN];
     int v,n,p,i,a,b,j,sumsg,cnt;
     edge *e;
//      freopen("trees.in","r",stdin);
     scanf("%d",&n);
     for(i=0,v=0;i<n;i++) {
	  firstv[i]=v;
	  scanf("%d",&p);
	  for(j=0;j<p-1;j++) {
	       scanf("%d%d",&a,&b);
	       AddEdge(a-1+v,b-1+v);
	       AddEdge(b-1+v,a-1+v);
	  }
	  v+=p;
     }
     for(i=0,sumsg=0;i<n;i++)
	  sumsg^=CountSG(firstv[i]);
     if(sumsg) {
	  for(i=0,cnt=0;i<n;i++)
	       for(e=adj[firstv[i]];e;e=e->next)
		    if((sumsg^sg[firstv[i]]^sg[e->w])==0)cnt++;
	  printf("1 %d\n",cnt);	       
     }
     else {
	  for(i=0,cnt=0;i<n;i++)
	       if(sumsg^sg[firstv[i]])cnt++;
	  printf("2 %d\n",cnt);	       
     }
     return 0;
}



