// BigBrother (vertex cover 10)  --- mjd@cs.auckland.ac.nz
//
#include <iostream>
#include <string>
#include <cassert>
#include <vector>
#include <algorithm>
#include <queue>
#include <sstream> 

//#define WATCH
#define NODEBUG

using namespace std;

typedef vector<int> NLIST;  	// node (neighbor) list 
typedef vector< NLIST > ADJLIST;
				
class Graph  // view as undirected graph
{
private:
   ADJLIST adj;  // adjacency lists.

public:  
   // creators + destroyers
   //
   Graph(int n) : adj(n) { }
   Graph(const Graph &G) : adj(G.adj) {} 

   ~Graph() {}

   // stream I/0
   //
   friend ostream& operator<<(ostream&, const Graph&);
   friend istream& operator>>(istream&, Graph&);

   // mutators
   //
   bool addArc(int u, int v)  
   {
     if ( isArc(u,v) ) return false;
     adj[u].push_back(v);
     return true;
   }

   bool addEdge(int u, int v)
   {
     return addArc(u,v) && addArc(v,u);
   }

   // accessors
   //
   int order() const { return adj.size(); }

   bool isArc(int u, int v) const
   {
     int n = order();
     assert(u >= 0 && u < n);
     assert(v >= 0 && v < n);
     assert(u != v);
  
     NLIST::const_iterator it = find( adj[u].begin(), adj[u].end(), v );
     if ( it==adj[u].end() ) return false;
     else return true;
   }

   bool isUndirected() const 
   {
     int n=order();
     for (int i=0; i<n-1; i++)
      for (int j=i+1; j<n; j++)
        if (isArc(i,j) != isArc(j,i)) return false;
     return true;
   }

   int degree(int u) const { return adj[u].size(); }

   int size() const
   {
     int size=0;
     for (int i=0; i<order(); i++) size += degree(i);
#ifdef DIGRAPH
     return size;
#else
     return size/2;
#endif
   }

   const NLIST neighbors(int u) const { return (const NLIST&) adj[u]; }

   // mutators
   //
   bool rmArc(int u, int v)  // false if doesn't exist
   {
     int n = order();
     const NLIST::iterator it = find( adj[u].begin(), adj[u].end(), v );
     if ( it==adj[u].end() ) return false;
     adj[u].erase(it);
     return true;
   }
   //
   bool rmEdge(int u, int v) { return rmArc(u,v), rmArc(v,u); }

   bool rmNode(int u)  
   {
     int n = order();
     assert(u>=0 && u<n);

     for (int i=0; i<n; i++) // digraph safe version -- check all lists
     {
        if (i==u) continue;
        NLIST::iterator it = adj[i].begin();
        while (it != adj[i].end())
        {
          if (*it == u)  { adj[i].erase(it); continue; }
          if (*it > u)  *it = *it - 1;
          it++;
        }
     } 
     adj.erase(adj.begin()+u); // finally delete list for u
   }
};

ostream& operator<<(ostream& o, const Graph& G)
{
  o << G.order() << "\n";
  for (int i=0; i<G.order(); i++)
  {
    for (int j=0; j<G.adj[i].size(); j++) o << G.adj[i][j] << " ";
    o << "\n";
  }
  return o;
}

istream& operator>>(istream& in, Graph& G) 
{
   string line;
   int n;
   getline(cin,line);
   istringstream lineIn(line);
   lineIn >> n;

   G.adj.resize(n);
   for (int i=0; i<n; i++) { G.adj[i].resize(0); }

   for (int v1=0; v1<n; v1++)
   {
      getline(cin, line);
      istringstream lineIn(line);
      int deg; lineIn >> deg;
      int v2; while (lineIn>>v2)
      {
         assert(v1!=v2);
         bool ans=G.addArc(v1,v2);
         assert(ans);
         deg--;
      }
      assert(deg==0);
   }
   return in;
}

//----------------------------------------------------------------------

// checks for potential VC -- assume cover is a sorted list of vertices.
bool checkCover(const Graph &G, const vector<int> &cover, int k)
{
  int n = G.order();

  int c=0;
  for (int i=0; i<n; i++) 
  {
     if (cover[c]==i) { if (c<k-1) c++; continue; }
     const NLIST N = G.neighbors(i);
     for (int j=0; j<N.size(); j++)
     {
       vector<int>::const_iterator it = find( cover.begin(), cover.end(), N[j] );
       if ( it==cover.end() ) { return false; }
     }
  }
  return true;
}

/*
 * Pick all k subsets of a graph and see if G\{v1,v2,...vk} has
 * any edges.
 */
bool vcLazy(const Graph &G, int k)
{
  int n = G.order();

  if ( k >= n ) return true;

  vector<int> cover(k);
  int i; for (i=0; i<k; i++) cover[i]=i;

  while (true)
  {
    if (checkCover(G,cover,k)) return true;

    for (i=k-1; i>=0; i--)
    {
      if (cover[i] < n-(k-i))
      {
        cover[i]++;
        for (int j=i+1; j<k; j++) cover[j]=cover[j-1]+1;
	break;
      }
    }
    if (i<0) return false;
  }
}


// Buss' fixed-parameter algorithm:  O( k * n + 2^k * k^(2k+2) )
//
//  1) Find all vertices of degree more than k (say b of them).
//  2) If b > k then answer 'no', other remove these b vertices.
//  3) If the resulting graph has more than k * (k-b) edges answer 'no'.
//  4) Use brute-force algorithm on remaining graph with k' = k-b.
//
bool vcBuss(Graph &G, int k)
{
  int n=G.order();

  if ( k >= n-1 ) return true;
  if (G.size()==0) return true;
  if ( k == 0 ) return false;
  if ( k <= 1 ) return vcLazy(G,k);  // cut-off to exhaustive search

  vector<int> deg(n);

  int b = 0; // number of big degree vertices
  for (int i=0; i<n; i++)
  {
    deg[i]=G.degree(i);

    if (deg[i] == 0)  // easy isolated vertex case
    {
        G.rmNode(i);
        return vcBuss(G,k);
    }

    if (deg[i] == 1)  // oops, let's take care of easy pendant case
    {
      int j=G.neighbors(i).at(0);
      if (i>j) { G.rmNode(i); G.rmNode(j); }
      else { G.rmNode(j); G.rmNode(i); }
      return vcBuss(G,k-1);
    }

    if (deg[i] > k) b++;
  }

  if (b==0)
  {
    // do decision tree search
    Graph G0(G), G1(G);
    int e = G.neighbors(0).at(0);
    G0.rmNode(0); G1.rmNode(e); 
    Graph G01(G1);
    if (deg[0] >= deg[e]) // try largest deg of 0 and e in VC first
    {
      if (vcBuss(G0,k-1)) return true;
      if (vcBuss(G1,k-1)) return true;
    }
    else
    {
      if (vcBuss(G1,k-1)) return true;
      if (vcBuss(G0,k-1)) return true;
    }
    G01.rmNode(0);  // delete both 0 and e (1 was deleted above)
    return vcBuss(G01,k-2);
  }
  else if (b>k) return false;
  else
  {
    for (int i=n-1; i>=0; i--)  // do in reverse to preserve deg values
    {
      if (deg[i] > k) G.rmNode(i);
    }

    if (G.size() > k*(k-b)) return false;
    else
    if (G.size() <= k-b) return true;

    return vcBuss(G,k-b);
  }
}

//----------------------------------------------------------------------

int main(int argc, char** argv)
{
  int k=10;
  if (argc > 1) k = atoi(argv[1]);

  int x=0;
  while (true)
  {
    Graph G(0);
    cin >> G;
    int n=G.order();
    if (n==0) break;
    assert(n<=2500);
    assert( G.isUndirected() );

    cout << "Graph " << ++x << ": " << (vcBuss(G,k)? "yes":"no") << endl;
    //cout << "Graph " << ++x << ": " << (vcLazy(G,k)? "yes":"no") << endl;
  }
}

