/*
	Problem: 	A: Team them up!
	Description:	find two (as equal as possible) partitions in an inverse of graph
	Class:		graphs
	Subclass:	min-max
	Algorithm:	finding partitions in a bipartition graph O(n^2), dynamic programming O(n^2)
	Author:		Josef Zlomek
	Date:		Mar 9, 2002
*/

#include <stdio.h>

#define N 100

int n, np;	/* number of persons, number of partitions */
int s[N][N];	/* the matrix of neighbourhood */
int part[N];	/* which partition is the vertex in */
int sizepart[N+N];	/*size of partititons */

int last[N+1][N+1];	/*last partition added to sum*/
int point[N+1];
int group[N];
int ng1;
int sum;

int q[N*N];	/* queue*/
int qs, qe;	/* queue start and end */

int main()
{
  int i, j, x;
	scanf("%d", &n);
//  for (;;)
  {

    /* create full graph as a matrix of neighbourhood*/
    for (i=0;i<n;i++)
    {
      for(j=0;j<n;j++)
	s[i][j]=1;
      s[i][i]=0;
    }

    /* remove some edges */
    for(i=0;i<n;i++)
    {
      for (;;) {
	scanf ("%d", &x);
	if (x==0) break;
	s[i][x-1]=0;
      }
    }

    /* if there is an edge it should be bidirectional (edge means that this 2
     * can't be in the same partition) */
    for(i=0;i<n;i++)
      for(j=0;j<n;j++)
	s[i][j] |= s[j][i];

    
    /* no vertex has a color*/
    for(i=0;i<n;i++)
      part[i]=-1;

    /* Find the coloring */
    np=0;
    for(i=0;i<n;i++)
      if(part[i]<0)
      {
	q[qs=0]=i;
	qe=1;
	part[i]=np;
	while(qs!=qe)
	{
	  x = q[qs++];
	  for (j=0;j<n;j++)
	  {
	    if(s[x][j])
	    {
	      if(part[j]<0)
	      {
		part[j]=part[x]^1;
		q[qe++]=j;
	      } 
	      else if (part[j] == part[x])
		goto no_solution;
	    }
	  }
	}
	np+=2;
      }

    /* compute the size of groups of vettices of the same color.*/
    for(i=0;i<np;i++)
      sizepart[i]=0;
    for(i=0;i<n;i++)
      sizepart[part[i]]++;

    /* dynamic programming*/
    for(i=0;i<=n;i++)
    {
      for(j=0;j<=n;j++) last[i][j]=-1;
      point[i]=0;
    }

    point[0]=1;
    sum=0;
    for(i=0;i<np;i+=2)
    {
      for(j=n;j>=0;j--)
	if(point[j])
	{
	  int a = j;
	  int b = sum-j;
	  point[j]=0;
	  last[a+sizepart[i]][b+sizepart[i+1]]=i;
	  last[a+sizepart[i+1]][b+sizepart[i]]=i+1;
	  point[j+sizepart[i]]=1;
	  point[j+sizepart[i+1]]=1;
	}
      sum += sizepart[i]+sizepart[i+1];
    }

    for(i=0;i<n;i++)
      group[i]=0;
    /* prepare for printing results*/
    ng1=0;
    for(i=n/2;i>=0;i--)
      if(last[i][sum-i]>=0)
      {
	ng1=i;
	while(i>0)
	{
	  int p = last[i][sum-i];
	  for(j=0;j<n;j++)
	    if(part[j]==p)
	      group[j]=1;
	  sum-=sizepart[p]+sizepart[p^1];
	  i-=sizepart[p];
	}
	break;
      }

    /* print results */
    printf ("%d", ng1);
    for(i=0;i<n;i++)
      if(group[i])
	printf(" %d",i+1);
    printf ("\n");
    printf ("%d", n-ng1);
    for(i=0;i<n;i++)
      if(!group[i])
	printf(" %d",i+1);
    printf ("\n");

    return 0;

no_solution:
    printf ("No solution\n");
  }
  
  return 0;
}
