program e;
const
  MaxN = 1000;
var
  P, C: Integer;
  
  Con: array[1..MaxN, 1..MaxN] of Boolean;
  Color, See: array[1..MaxN] of Integer;
  ActColor, MaxA, Parts: Integer;
  
  procedure Search(V: Integer);
  var
    I, A: Integer;
  begin
    Color[V]:= ActColor;
    ActColor:= ActColor + 1;
    See[V]:= Color[V];
    
    A:= 0;
    for I:= 1 to P do
    if Con[V, I] then 
    if Color[I] = 0 then
    begin
      Search(I);
      if See[I] >= Color[V] then Inc(A) else 
      if See[V] > See[I] then See[V]:= See[I];
    end else
    if See[V] > Color[I] then See[V]:= Color[I];
    
    if Color[V] = 1 then A:= A - 1;
    if A > MaxA then MaxA:= A;
    
    {Writeln('Vrchol ', V, ' ', A);}
  end;
  
  procedure WriteState;
  var
    I: Integer;
  begin
    for I:= 1 to P do
    Writeln(I, ' ', Color[I], ' ', See[I]);
  end;
  
var  
  I, J, X, Y: Integer;
begin
  while True do
  begin
    Readln(P, C);
    if P = 0 then Break;
    if P >= 1000 then Break;
    
    for I:= 1 to P do
    for J:= 1 to P do
    Con[I, J]:= False;
    
    for I:= 1 to C do
    begin
      Readln(X, Y);
      Con[X + 1, Y + 1]:= True;
      Con[Y + 1, X + 1]:= True;
    end;
    
    for I:= 1 to P do Color[I]:= 0;
    
    MaxA:= 0;
    Parts:= 0;
    for I:= 1 to P do
    if Color[I] = 0 then 
    begin
      ActColor:= 1;
      Parts:= Parts + 1;
      Search(I);
    end;
    {WriteState;}
    
    Writeln(MaxA + Parts);
  end;
end.