#include <cstdlib>
#include <stdio.h>
#include <iostream>
#include <set>
#include <list>

using namespace std;

    typedef struct polaczenie polaczenie;
struct polaczenie {
    long numer;
    polaczenie *nastepne;
};

int main(int argc, char *argv[])
{
  long n, m, p, a, b;
  scanf ("%li %li %li", &n, &m, &p);
  long pol[n];
  polaczenie * lista[n]; //array of pointers
  std::set<long> zbiory;
  long i;
  for (i=0; i<n;i++)
  {
      lista[i]=NULL;
      pol[i]=0;
  }
  /*long j;
  for (j=0; j<n;j++)
  {
      if (lista[j]!=NULL) printf("problem");
  }*/
  for (i=0;i<m;i++)
  {
      scanf ("%li %li", &a, &b);
      a--;
      b--; //off by one. Lol.
      pol[a]=pol[a]+1;
      pol[b]=pol[b]+1;
      polaczenie * noweb;
      noweb = (polaczenie*)malloc(sizeof(polaczenie));
      noweb->numer = a;
      noweb->nastepne = lista[b];
      (lista[b]) = noweb;
      polaczenie * nowea;
      nowea = (polaczenie*)malloc(sizeof(polaczenie));
      nowea->numer = b;
      nowea->nastepne = (lista[a]);
      (lista[a]) = nowea;
      //printf ("[%li,%li]\n", nowea->numer, noweb->numer);
  }
  //pierwsze wyszukanie złych miast
  
  
 
            
  for (i=0; i<n; i++)
  {
      if (pol[i]<p) //dodaj do kolejki/zbioru miasta połączone z tym, usuń te miasto, zmniejsz o 1 liczbę poołączeń sąsiadów.;
      {
          while (lista[i]!=NULL)
          {
              zbiory.insert((lista[i])->numer);
              pol[(lista[i])->numer]=pol[(lista[i])->numer]-1;
              lista[i] = lista[i]->nastepne;
              pol[i]=-1;
          }
      }
  }
  
  while (zbiory.size()>0)
  {
        std::set<long>::iterator it;
        it = zbiory.begin();
        long mit = *it;
        zbiory.erase(it);
        if (pol[mit]<p)
        {
            while (lista[mit]!=NULL)
            {
                zbiory.insert((lista[mit])->numer);
                pol[(lista[mit])->numer]=pol[(lista[mit])->numer]-1;
                lista[mit] = lista[mit]->nastepne;
                pol[mit]=-1;
            }
        }
  }
  //przycięte. Można szukać zbiorów.
  std::list<long> najwiekszy;
  std::list<long> aktualny;
  for (i=0; i<n;i++)
  {
      
      if (pol[i]>0)
      {
          long iterator;
          std::list<long>::iterator it;
          pol[i]=-1;
          aktualny.push_back(i); //znaleziony pierwszy element zbioru
          iterator =0;
          for (it = aktualny.begin(); it!=aktualny.end(); ++it)
          {
              while (lista[*it]!=NULL)
              {
                    if (pol[(lista[*it])->numer]>0)
                    {
                        pol[(lista[*it])->numer]=-1;
                        aktualny.push_back((lista[*it])->numer);
                    }
                    lista[*it] = (lista[*it])->nastepne;
              }
          }
          if (aktualny.size()>najwiekszy.size())
          {
              najwiekszy = aktualny;
          }
          aktualny.clear();
      }
  }
  if (najwiekszy.size()==0) { printf ("NIE"); /*system("PAUSE");*/ return 0;}
  printf ("%li\n", najwiekszy.size());
  std::list<long>::iterator it;
  najwiekszy.sort();
  for (it = najwiekszy.begin(); it!=najwiekszy.end(); ++it)
      printf ("%li ", (*it)+1);
  
  
  /*for (i=0; i<n; i++)
  {
      printf ("\n %li (%li):", i, pol[i]);
      while (lista[i]!=NULL)
      {
            printf ("%li ",(lista[i])->numer);
            (lista[i]) = (lista[i])->nastepne;
      }
  }*/
    //system("PAUSE");
    return 0;
}
