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

#define ll long long

using namespace std;



#define N 200000

#define WHITE 0  // 未訪問

#define BLACK 1  // 訪問ずみ



// 連結成分の番号を振る関数

void dfs(int n, int comp[], vector<int> G[])

{

    int i, j, vertex, neighbor, color[N];

    stack<int> S;

    int ans[N] = {};

    // 初期状態

    for (i = 0; i < n; i++)

        color[i] = WHITE;



    for (i = 0; i < n; i++) {

        if (color[i] == WHITE) {

            // dfs

            S.push(i);

            while (!S.empty()) {

                vertex = S.top();

                S.pop();

                color[vertex] = BLACK;  // 訪問済みにする

                comp[vertex] = i;       // 連結成分の番号を振る



                for (j = 0; j < (int)G[vertex].size(); j++) {

                    neighbor = G[vertex][j];  // 隣接している頂点：友人

                    if (color[neighbor] == WHITE)

                        S.push(neighbor);

                }

            }

        }

    }

}



int main()

{

    int i, n, m, s, t;

    int comp[N];       // 連結成分の番号

    vector<int> G[N];  // グラフを表現する隣接リスト



    cin >> n >> m;

    // 隣接リストを作成

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

        cin >> s >> t;

        --s;

        --t;

        G[s].push_back(t);

        G[t].push_back(s);

    }



    // グラフを連結成分に分ける

    dfs(n, comp, G);



    int ans[N] = {};

    int temp = 0;

    for (int j = 0; j < n; j++) {

        //std::cout << j << " " << comp[j] << std::endl;

        ++ans[comp[j]];

    }

    for (auto v : ans) {

        temp = std::max(v, temp);

    }

    std::cout << temp << std::endl;

    return 0;

}

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

#define ll long long

#define ld long double

#define rep(i, n) for (ll i = 0; i < (ll)(n); i++)

#define Yes() std::cout << "Yes" << std::endl

#define No() std::cout << "No" << std::endl

#define Say(s) std::cout << s << std::endl

const ll MOD = 1000000007;

const ll INF = 1061109567;



int main()

{

    ll n, m;

    std::vector<std::array<ll, 2>> k;

    std::cin >> n >> m;

    rep(i, m)

    {

        ll temp_1, temp_2;

        std::cin >> temp_1 >> temp_2;

        --temp_1;

        --temp_2;

        k.push_back({temp_1, temp_2});

    }

    // そもそもdfsは適用範囲が広く,これは単純なグラフの時にしか使えない

    using Graph = std::vector<std::vector<ll>>;

    /*auto make_graph = [&](const ll& num_points, const ll& num_sides, const auto& side_pairs) {

        //libproton 1.1.0

        //num_pointsは頂点数,num_sidesは辺数,side_pairsはvector::vector<ll>に相当するものを入力してください。

        //ただし二つ目のvectorは二つの要素しかないことを想定している

        //グラフ型(G[index]に頂点indexから直接行ける点の列挙が入っている)を返す

        //graphのiteratorが1次元の時しか対応していない

        Graph G(num_points);

        for (ll i = 0; i < num_sides; ++i) {

            G[side_pairs.at(i).at(0)].push_back(side_pairs.at(i).at(1));

            // 無向グラフの場合は以下を追加

            // G[side_pairs.at(i).at(1)].push_back(side_pairs.at(i).at(0));

        }

        return G;

    };*/

    ll temp_temp = 0;

    std::vector<bool> graph_seen(n, false);  //100には頂点数を入れる。下のdfsは再帰なので外でdfsを定義する必要あり。

    std::function<void(const Graph&, const ll&, std::vector<bool>&)> dfs_mono = [&](const Graph& dfs_G, const ll& start_point, std::vector<bool>& dfs_seen) {

        //libproton 1.1.0

        //graphのiteratorが1次元の時しか対応していない

        //dfs_GにはGraph型を, start_pointには探索開始点を, dfs_seenには頂点数の大きさを持った全false配列を入れてください。

        //返す値はない。dfs_seenが訪問済みでtrueに切り替わっているはず。やりたい動作は使用時にこのなかに追記してください。

        dfs_seen[start_point] = true;  // start_point を訪問済にする

        ++temp_temp;

        // この部分にやりたい動作を書くと良い



        // start_point から行ける各頂点 next_v について

        for (auto next_v : dfs_G[start_point]) {

            if (dfs_seen[next_v])

                continue;  // next_v が探索済だったらスルー



            // この部分にやりたい動作を書くと良い



            dfs_mono(dfs_G, next_v, dfs_seen);  // 再帰的に探索

        }

        return 0;

    };

    Graph G(n);

    for (ll i = 0; i < k.size(); ++i) {

        G[k.at(i).at(0)].push_back(k.at(i).at(1));

        G[k.at(i).at(1)].push_back(k.at(i).at(0));

    }

    Graph friend_graph = G;

    std::vector<ll> number_menber;

    for (ll i = 0; i < n; ++i) {

        temp_temp = 0;

        if (graph_seen[i] == false) {

            dfs_mono(friend_graph, i, graph_seen);

            number_menber.push_back(temp_temp);

        }

    }

    std::sort(number_menber.begin(), number_menber.end());

    Say(number_menber[number_menber.size() - 1]);

    return 0;

}