#line 1 "/home/parallels/kyopro/cplib/template.cpp"
#include<bits/stdc++.h>
using namespace std;

#define REP(i,n) for(int i = 0;i < n;i++)
#define mp make_pair
#define pb push_back
#define eb emplace_back
#define all(x) (x).begin(),(x).end()

template<class T> bool chmax(T& a,T b){ if(a < b){ a = b; return true; }else return false; }
template<class T> bool chmin(T& a,T b){ if(a > b){ a = b; return true; }else return false; }

using ll = long long;
using ld = long double;
using vi = vector<int>;
using vl = vector<ll>;
using Pi = pair<int,int>;
using Pl = pair<ll,ll>;
using vpi = vector<Pi>;
using vpl = vector<Pl>;

void lyn(){
  cin.tie(0);
  ios::sync_with_stdio(false);
}

#line 1 "/home/parallels/kyopro/cplib/debug.cpp"
#define debug(arr) cout << #arr << " = " << arr << '\n'
#define debug2(a,b) cout << "[" << #a << "," << #b << "] = " << "[" << a << "," << b << "]" << '\n'
template<class T> ostream &operator << (ostream& out, const vector<T>& arr) {
	cout << "{"; for (int i = 0; i < arr.size(); i++)cout << (!i ? "" : ", ") << arr[i]; cout << "}";
	return out;
}
template<class T> ostream &operator << (ostream& out, const vector<vector<T> >& arr) {
	cout << "{\n"; for (auto& vec : arr)cout << "  " << vec << ",\n"; cout << "}";
	return out;
}
template<class S,class T> ostream &operator << (ostream& out, const pair<S,T>& p){
  cout << "{" << p.first << "," << p.second << "}" << '\n';
  return out;
}
template<class T> istream &operator >> (istream& in, vector<T>& arr) {
	for (auto& i : arr)cin >> i; return in;
}
#line 1 "/home/parallels/kyopro/cplib/graph/template.cpp"
template<class T> struct Edge{
  int from,to; T cost;
  Edge(int from,int to,T cost):from(from),to(to),cost(cost){}
  Edge(){}
};
template<class T> struct Graph{
  int n;
  vector<vector<Edge<T>>> g;
  Graph(int n):n(n){
    g.resize(n);
  }
  void add_edge(int from,int to){
    g[from].emplace_back(from,to,1);
  }
  void add_edge(int from,int to,T cost){
    g[from].emplace_back(from,to,cost);
  }
  vector<Edge<T>>& operator[](int i){ return g[i]; }
};
#line 2 "/home/parallels/kyopro/cplib/graph/problems/count_connectives.cpp"
template<class T> struct CountConnectives
{
  Graph<T> G;
  vector<bool> used;
  vector<int> root,SizeOfMyGroup,ConnectedID;
  CountConnectives(Graph<T>& G):G(G){

  }
  void dfs(int st,int x,int id){
    used[x] = true;
    root[x] = st;
    ConnectedID[x] = id;
    SizeOfMyGroup[st]++;
    for(auto _next : G[x]){
      if(!used[_next.to]){
        dfs(st,_next.to,id);
      }
    }
  }
  int solve(){
    used.assign(G.n,false);
    ConnectedID.assign(G.n,-1);
    root.assign(G.n,-1);
    SizeOfMyGroup.assign(G.n,0);
    int res = 0;
    for (int i = 0; i < G.n; i++) {
      if (!used[i]) {
        dfs(i,i,res);
        res++;
      }
    }
    for (int i = 0; i < G.n; i++) {
      SizeOfMyGroup[i] = SizeOfMyGroup[root[i]];
    }  
    return res;
  }
};
#line 3 "main.cpp"

int main(int argc, char const* argv[])
{
  int n,m;cin >> n >> m;
  Graph<int> G(n);
  REP(i,m){
    int a,b;cin >> a >> b;
    a--,b--;
    G.add_edge(a,b);
    G.add_edge(b,a);
  }
  CountConnectives<int> CC(G);
  CC.solve();
  int ans = 1;
  for(auto e : CC.SizeOfMyGroup){
    chmax(ans,e);
  }
  cout << ans << '\n';
  return 0;
}


Measured memory_bytes: 39932