#include <bits/stdc++.h>
using namespace std;
#ifndef ONLINE_JUDGE
#include <bits/extc++.h>
using namespace __gnu_pbds;
typedef tree<int, null_type, less<int>, rb_tree_tag, tree_order_statistics_node_update> ost;
#endif
typedef long long ll;
typedef vector<int> vi;
typedef pair<int, int> ii;
typedef tuple<int, int, int> iii;
typedef vector<pair<int, int> > vii;
typedef vector<vector<int> > vvi;

#define SETIO(); ios_base::sync_with_stdio(false); cin.tie(0);
#define gcd(a,b) __gcd(a, b)
#define lcm(a, b) (a*b)/gcd(a,b)
#define sz(x) (int)(x).size()
#define FOR(i, n) for (int i=0; i < n; ++i)
#define ROF(i, n) for (int i=n-1; i >= 0; --i)
#define f first
#define s second
#define mp make_pair
#define eb emplace_back
#define pb push_back
#define pf push_front
#define pof pop_front
#define pob pop_back
#define all(x) begin(x), end(x)

template<typename T> void print(vector<T> &vec, string end = "\n") {
    if (sz(vec) < 1) {cout << "empty vector\n"; return;}
    for (auto i=0; i < sz(vec); ++i) {
    if (i == 0) {cout << "[" << vec[i];} else {cout << vec[i];}if (i != sz(vec)-1) {cout << ", ";} else {cout << "]" + end;}}}
template<typename T> void print(T primitive, string end = "\n") {cout << primitive << end;}

class Point {
    int x, y;
};
class Graph {
    private:
        vvi graph;
        vector<bool> vis;
        int size, numComps=0, numNode=0;
        void subdfs(int node) {vis[node] = true;for (auto n: graph[node]) {if (!vis[n]) {subdfs(n);}}}
    public:
        Graph(int N) {
            graph.assign(N, vector<int>());
            vis.assign(N, false);
            size = N;
        }
        void cleanVis() {vis.assign(size, false);}
        void addEdge(int u, int v) {graph[u].eb(v);graph[v].eb(u);}
        int numNodes(int node=0) {
        int viscount=1;vis[node] = true;for (auto neighbor: graph[node]) {if (!vis[neighbor])viscount += numNodes(neighbor);}return numNode =viscount;}
        void dfs(int start=0) {vis.assign(size, false);subdfs(start);}
        int numComponents(int start) {if (numComps != 0){return numComps;}for (auto i=start; i < size; ++i) {if (!vis[i]) {numComps++;dfs(i);}}
        return numComps;}
        int shortestBFS(int source, int dest) {
            cleanVis();
            queue<int> bfsq, distq;
            bfsq.push(source);
            distq.push(0);
            int chk, dist;
            vis[source] = true;
            while (!bfsq.empty()) {
                chk = bfsq.front(); bfsq.pop();dist = distq.front(); distq.pop();
                if (chk == dest) {
                    return dist;}for (auto neighbor: graph[chk]) {if (!vis[neighbor]) {vis[neighbor] = true;bfsq.push(neighbor);distq.push(dist+1);}}}
            return -1;}
};
class UnionFind {
    private:
        vi p, rank, setSize;
        int numSets;
    public:
        UnionFind(int N) {
            p.assign(N, 0); FOR(i, N) p[i] = i;
            rank.assign(N, 0);
            setSize.assign(N, 1);
            numSets = N;
        }
    int findSet(int i) {return (p[i] == i) ? i : (p[i] = findSet(p[i]));}
    bool isSameSet(int i, int j) {return findSet(i) == findSet(j);}
    int numDisjointSets() {return numSets;}
    int sizeOfSet(int i) {return setSize[findSet(i)];}
    void unionSet(int i, int j) {
        if (isSameSet(i, j)) return;
        int x = findSet(i), y = findSet(j);
        if (rank[x] > rank[y]) swap(x, y);
        p[x] = y;
        if (rank[x] == rank[y]) ++rank[y];
        setSize[y] += setSize[x];
        --numSets;
    }
};
unordered_set<int> graph[200001];
bool vis[200001];
int dfs(int i) {
    vis[i]=true;
    int ret=1;
    for(auto &n:graph[i]){
        if(!vis[n]){
            ret+=dfs(n);
        }
    }
    return ret;
}
int N, M;
int main() {
    SETIO();
    cin >> N >> M;
    int a, b;
    FOR(i, M) {
        cin >> a >> b;
        graph[a].insert(b);
        graph[b].insert(a);
    }
    int ans=0;
    for (int i=1;i<=N;i++) {
        if (!vis[i]) {
            ans=max(ans,dfs(i));
        }
    }
    cout << ans << '\n';
    return 0;
}
/* stuff you should look for
    * int overflow, array bounds
    * special cases (n=1?)
    * do smth instead of nothing and stay organized
    * WRITE STUFF DOWN
    * CHECK IF DEBUGGING OUTPUT BLOCKS ANSWER
*/




Measured memory_bytes: 39712