// Slower C++ solution:
#include <bits/stdc++.h>

#define ss second

#define ff first

#define all(x) x.begin(), x.end()



using namespace std;

using ll = long long;

using pii = pair<ll, ll>;



const ll oo = 1e18 + 7;

const ll mod = 1e9 + 7, maxn = 2e5 + 10;  

const long double PI = acos(-1);

int cnt = 1, ps[maxn], sz[maxn];



int find(int x){

    if (x == ps[x]) return x;

    return ps[x] = find(ps[x]);

}



void uni(int a, int b){

    a = find(a);

    b = find(b);



    if (a == b) return;



    ps[a] = b;

    sz[b] += sz[a];

    cnt = max(cnt, sz[b]);

}



void init(){

    iota(ps, ps+maxn, 0);

    for (int i=0; i<maxn; i++) sz[i] = 1;

}



int main (){

    ios_base::sync_with_stdio(false);

    cin.tie(0);

    int n,m;

    cin >> n >> m;

    init();



    for (int i=0; i<m; i++){

        int a, b;

        cin >> a >> b;

        uni(--a, --b);

    }



    cout << cnt << endl;

    return 0;   

}

// Faster C++ solution for the same problem (measured speedup: 2.5640865212787847x):
#include <bits/stdc++.h>



using namespace std;



template <typename A, typename B>

string to_string(pair<A, B> p);

 

template <typename A, typename B, typename C>

string to_string(tuple<A, B, C> p);

 

template <typename A, typename B, typename C, typename D>

string to_string(tuple<A, B, C, D> p);

 

string to_string(const string& s) {

  return '"' + s + '"';

}

 

string to_string(const char* s) {

  return to_string((string) s);

}

 

string to_string(bool b) {

  return (b ? "true" : "false");

}

 

string to_string(vector<bool> v) {

  bool first = true;

  string res = "{";

  for (int i = 0; i < static_cast<int>(v.size()); i++) {

    if (!first) {

      res += ", ";

    }

    first = false;

    res += to_string(v[i]);

  }

  res += "}";

  return res;

}

 

template <size_t N>

string to_string(bitset<N> v) {

  string res = "";

  for (size_t i = 0; i < N; i++) {

    res += static_cast<char>('0' + v[i]);

  }

  return res;

}

 

template <typename A>

string to_string(A v) {

  bool first = true;

  string res = "{";

  for (const auto &x : v) {

    if (!first) {

      res += ", ";

    }

    first = false;

    res += to_string(x);

  }

  res += "}";

  return res;

}

 

template <typename A, typename B>

string to_string(pair<A, B> p) {

  return "(" + to_string(p.first) + ", " + to_string(p.second) + ")";

}

 

template <typename A, typename B, typename C>

string to_string(tuple<A, B, C> p) {

  return "(" + to_string(get<0>(p)) + ", " + to_string(get<1>(p)) + ", " + to_string(get<2>(p)) + ")";

}

 

template <typename A, typename B, typename C, typename D>

string to_string(tuple<A, B, C, D> p) {

  return "(" + to_string(get<0>(p)) + ", " + to_string(get<1>(p)) + ", " + to_string(get<2>(p)) + ", " + to_string(get<3>(p)) + ")";

}

 

void debug_out() { cerr << endl; }

 

template <typename Head, typename... Tail>

void debug_out(Head H, Tail... T) {

  cerr << " " << to_string(H);

  debug_out(T...);

}



#define debug(...) cerr << "[" << #__VA_ARGS__ << "]:", debug_out(__VA_ARGS__)



using ll = long long;

using ii = pair<int, int>;

using vi = vector<int>;



const int MAX { 1000010 };

const ll MOD { 1000000007 };

const double PI = acos(-1.0);



class UFDS {

public:

    vector<int> parents, rank;



    UFDS(int N) {

        rank.assign(N, 1);

        parents.assign(N, 0);

        for(int i = 0; i < N; ++i) parents[i] = i;

    }



    int findSet(int i) {

        if (parents[i] == i) return i;

        return parents[i] = findSet(parents[i]);

    }



    bool isSameSet(int i, int j) {

        return findSet(i) == findSet(j);

    }



    void unionSet(int i, int j) {

        if (!isSameSet(i, j)) {

            int x = findSet(i), y = findSet(j);

            if (rank[x] > rank[y]) swap(x, y);



            parents[x] = y;

            rank[y]+=rank[x];

        }

    }

};



int main() {

    ios::sync_with_stdio(false);

    cin.tie(0);



    int N, M;

    cin >> N >> M;



    UFDS ufds(N);



    for(int i=0; i<M; ++i){

        int A, B;

        cin >> A >> B;

        A--; B--;

        ufds.unionSet(A, B);

    }



    int maior = -1;

    for(int i=0; i<N; ++i){

        maior < ufds.rank[i] ? maior = ufds.rank[i] : maior;

    }



    cout << maior << endl;



    return 0;

}