stablegradients/pie-gem5-pairs huggingface dataset:
// Slower C++ solution:
#include<iostream>

#include <vector>

#include <list>

#include<set>

#include<algorithm>

#define pb emplace_back

#define ll long long

#define mp make_pair

#define PI acos(-1)

using namespace std;

ll n,m;

vector<ll>g[200005],v;

bool visit[200005];

set<ll>s;

void dfs(ll node)

{

    visit[node]=1;

    s.insert(node);

    for(auto child:g[node])

    {

        if(!visit[child])

            dfs(child);

    }

}

int main()

{

    ios_base::sync_with_stdio(false);

    cin.tie(0);

    cout.tie(0);

    ll i,j,k,x,y,z,t,b,c,d,a,l,r;

    cin>>n>>m;

    for(i=1; i<=m; i++)

    {

        cin>>a>>b;

        g[a].pb(b);

        g[b].pb(a);

    }

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

    {



        if(!visit[i])

        {

            dfs(i);

            v.pb(s.size());

            s.clear();

        }

    }

    sort(v.rbegin(),v.rend());

    if(v.size()==1)

        cout<<v[0]<<'\n';

    else

        cout<<(v[0]-v[1])+v[1]<<'\n';

}


























// Faster C++ solution for the same problem (measured speedup: 6.5850066947958625x):
#include <iostream>



using namespace std;

const int maxn = 200500;

int f[maxn];

int num[maxn];

// int x[maxn];

// int y[maxn];

int n,m,x,y;

int find_(int x){

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

    return f[x]=find_(f[x]);

}

void init() {

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

        f[i] = i;

}

void merge(int x,int y) {

    int fax = find_(x);

    int fay = find_(y);

    if(fax!=fay)

        f[fay] = fax;

}



int ans = 0;

int main()

{

    scanf("%d%d",&n,&m);    //n个点m组

    init();

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

        scanf("%d%d",&x,&y);

        merge(x,y);

    }

    for(int i = 1;i <= n;i++) 

        num[find_(i)]++;

    for(int i = 1;i <= n;i++) {

        if(ans < num[i])

            ans = num[i];

    }

    printf("%d\n",ans);

    return 0;

}
// Slower C++ solution:
#include<iostream>

#include <vector>

#include <list>

#include<set>

#include<algorithm>

#define pb emplace_back

#define ll long long

#define mp make_pair

#define PI acos(-1)

using namespace std;

ll n,m;

vector<ll>g[200005],v;

bool visit[200005];

set<ll>s;

void dfs(ll node)

{

    visit[node]=1;

    s.insert(node);

    for(auto child:g[node])

    {

        if(!visit[child])

            dfs(child);

    }

}

int main()

{

    ios_base::sync_with_stdio(false);

    cin.tie(0);

    cout.tie(0);

    ll i,j,k,x,y,z,t,b,c,d,a,l,r;

    cin>>n>>m;

    for(i=1; i<=m; i++)

    {

        cin>>a>>b;

        g[a].pb(b);

        g[b].pb(a);

    }

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

    {



        if(!visit[i])

        {

            dfs(i);

            v.pb(s.size());

            s.clear();

        }

    }

    sort(v.rbegin(),v.rend());

    if(v.size()==1)

        cout<<v[0]<<'\n';

    else

        cout<<(v[0]-v[1])+v[1]<<'\n';

}


























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



using namespace std;



int parent[200005];

int ranking[200005];

int n, m;



int get_parent(int a)

{

    return (parent[a] = parent[a] == a ? a : get_parent(parent[a]));

}



void join(int a, int b)

{

    if (get_parent(a) == get_parent(b))

        return;

    if (ranking[get_parent(a)] < ranking[get_parent(b)])

        swap(a,b);

    ranking[get_parent(a)] += ranking[get_parent(b)];

    parent[get_parent(b)] = parent[get_parent(a)];

}



int main()

{

    ios::sync_with_stdio(false);

    cin.tie(0);



    cin >> n >> m;



    for (int i = 1; i <= n; i++) {

        parent[i] = i;

        ranking[i] = 1;

    }



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

        int a, b;

        cin >> a >> b;

        join(a,b);

    }



    int ans = 0;

    for (int i = 1; i <= n; i++) {

        ans = max(ans, ranking[i]);

    }



    cout << ans << endl;

    return 0;

}
// Slower C++ solution:


#include<bits/stdc++.h>

using namespace std;

#include <ext/pb_ds/assoc_container.hpp>

#include <ext/pb_ds/tree_policy.hpp>

using namespace __gnu_pbds;

#define ordered_set tree<int, null_type,less<int>, rb_tree_tag,tree_order_statistics_node_update>

#define ll long long

#define si(n) scanf("%d",&n);

#define PI acos(-1.0)

#define sl(n) scanf("%lld",&n);

#define sf(n) scanf("%lf",&n);

#define ss(n) scanf("%s",n);

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

#define for1(i,n) for(ll i=1;i<=n;i++)

#define forc(i,j,n) for(ll i=j;i<n;i++)

#define pb push_back

#define sor(n) sort(n.begin(),n.end())

#define sorcmp(n) sort(n.begin(),n.end(),cmp)

#define rev(n) reverse(n.begin(),n.end())

#define pi(x)  printf("%d",x);

#define pl(x)  printf("%lld",x);

#define pf(x)  printf("%.10lf",x);

#define ps(x)  printf("%s",x);

#define en() printf("\n");

#define random_shuffle(r...)random_shuffle(r,[](int _){return rand()%_;})

#define SQR(a) (a)*(a)

#define sp(x) fixed<<setprecision(x)

#define mod 1000000007

#define endl '\n'

#define pii pair<int,int>

#define pll pair<ll,ll>

#define bug cout<<"Here"<<endl

void fastio(){ios_base::sync_with_stdio(false);cin.tie(NULL);cout.tie(NULL);}

template <typename T> T POW(T B,T P){ if(P==0) return 1; if(P&1) return B*POW(B,P-1);  else return SQR(POW(B,P/2));}

ll powmod(ll a, ll b){ll ans = 1;while(b){if(b&1) ans = ans*a%mod;a = a*a%mod;b >>= 1;}return ans;}



#define mxn 200005

vector<int>g[mxn];

int vis[mxn];



int bfs(int x)

{

    vis[x]++;

    queue<int>q;

    q.push(x);

    int cnt=1;

    while(!q.empty())

    {

        int v=q.front();

        q.pop();



        for(auto u:g[v])

        {

            if(vis[u]) continue;

            vis[u]++;

            cnt++;

            q.push(u);

        }

    }



    return cnt;

}





int main()

{





    int n,m;

    cin>>n>>m;



    while(m--)

    {

        int a,b;

        cin>>a>>b;

        g[a].pb(b);

        g[b].pb(a);

    }

    int mx=-1;

    for(int i=1;i<=n;i++)

    {

        if(vis[i]) continue;

        mx=max(mx,bfs(i));

    }



    cout<<mx<<endl;











	return 0;

}




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



using namespace std;



int parent[200005];

int ranking[200005];

int n, m;



int get_parent(int a)

{

    return (parent[a] = parent[a] == a ? a : get_parent(parent[a]));

}



void join(int a, int b)

{

    if (get_parent(a) == get_parent(b))

        return;

    if (ranking[get_parent(a)] < ranking[get_parent(b)])

        swap(a,b);

    ranking[get_parent(a)] += ranking[get_parent(b)];

    parent[get_parent(b)] = parent[get_parent(a)];

}



int main()

{

    ios::sync_with_stdio(false);

    cin.tie(0);



    cin >> n >> m;



    for (int i = 1; i <= n; i++) {

        parent[i] = i;

        ranking[i] = 1;

    }



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

        int a, b;

        cin >> a >> b;

        join(a,b);

    }



    int ans = 0;

    for (int i = 1; i <= n; i++) {

        ans = max(ans, ranking[i]);

    }



    cout << ans << endl;

    return 0;

}
// Slower C++ solution:
#include<iostream>

#include <vector>

#include <list>

#include<set>

#include<algorithm>

#define pb emplace_back

#define ll long long

#define mp make_pair

#define PI acos(-1)

using namespace std;

ll n,m;

vector<ll>g[200005],v;

bool visit[200005];

set<ll>s;

void dfs(ll node)

{

    visit[node]=1;

    s.insert(node);

    for(auto child:g[node])

    {

        if(!visit[child])

            dfs(child);

    }

}

int main()

{

    ios_base::sync_with_stdio(false);

    cin.tie(0);

    cout.tie(0);

    ll i,j,k,x,y,z,t,b,c,d,a,l,r;

    cin>>n>>m;

    for(i=1; i<=m; i++)

    {

        cin>>a>>b;

        g[a].pb(b);

        g[b].pb(a);

    }

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

    {



        if(!visit[i])

        {

            dfs(i);

            v.pb(s.size());

            s.clear();

        }

    }

    sort(v.rbegin(),v.rend());

    if(v.size()==1)

        cout<<v[0]<<'\n';

    else

        cout<<(v[0]-v[1])+v[1]<<'\n';

}


























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

#define REP(i, a, b) for(int i = (int)a; i < (int)b; i++)

#define fastio ios_base::sync_with_stdio(0), cin.tie(0), cout.tie(0)

#define pb push_back

#define mp make_pair

#define st first

#define nd second

#define vi vector<int>

#define ii pair<int, int>

#define ll long long int

#define MAX 200010

#define MOD 1000000007

#define oo 0x7fffffff

#define endl '\n'

using namespace std;



int N, M;



class UFDS{

private: vi p, size;

public:

	UFDS(int N){

		size.assign(N+1, 1);p.assign(N+1, 0);

		iota(p.begin(), p.end(), 0);

	}

	int find_set(int i) {

		return (p[i] == i) ? i : find_set(p[i]);

	}

	bool same_set(int i, int j) { 

		return find_set(i) == find_set(j);

	}

	void union_set(int i, int j) {

		if(same_set(i, j))

			return;



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

		

		if(size[x] < size[y])

			swap(x, y);

		p[y] = x;

		size[x] += size[y];

	}

	int get_size(int i){

		return size[find_set(i)];

	}

};



int main()

{

   

	fastio;

	// freopen("input.txt", "r", stdin);

	// freopen("output.txt", "w", stdout);



	cin >> N >> M;

	UFDS udfs(N);

	REP(i, 0, M){

		int a, b;

		cin >> a >> b;

		udfs.union_set(a, b);

	}

	int ans = 0;

	REP(i, 1, N+1){

		// cout << udfs.find_set(i) << endl;

		ans = max(ans, udfs.get_size(i));

	}

	cout << ans << endl;



    return 0;

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

using namespace std;

struct unionfind{

    int par[200100];

    int rank[200100];



    void init(int n){

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

            par[i]=i;

            rank[i]=0;

        }

    }



    int find(int x){

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

        else return par[x] = find(par[x]);

    }



    void unite(int x, int y){

        x = find(x);

        y = find(y);

        if(x == y) return;

        if(rank[x]<rank[y]) par[x] = y;

        else{

            par[y] = x;

            if(rank[x] == rank[y]) rank[x]++;

        }

    }



    bool same(int x, int y){

        if(find(x)==find(y)) return true;

        else return false;

    }

};

int main(){

   long long n, m, ans=0, i, cnt[200100]={0}, a[200100], b[200100];

   unionfind g;

   cin >> n >> m;

   g.init(n);

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

       cin >> a[i] >> b[i];

       g.unite(a[i], b[i]);

   }



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

      cnt[g.find(i)]++;

   }

   for(auto x : cnt){

       ans=max(ans, x);

   }

   cout << ans <<endl;



   return 0;

}

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

using namespace std;

struct unionfind{

    int par[200100];

    int rank[200100];



    void init(int n){

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

            par[i]=i;

            rank[i]=0;

        }

    }



    int find(int x){

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

        else return par[x] = find(par[x]);

    }



    void unite(int x, int y){

        x = find(x);

        y = find(y);

        if(x == y) return;

        if(rank[x]<rank[y]) par[x] = y;

        else{

            par[y] = x;

            if(rank[x] == rank[y]) rank[x]++;

        }

    }



    bool same(int x, int y){

        if(find(x)==find(y)) return true;

        else return false;

    }

};

int main(){

   long long n, m, ans=0, i, a[200100], b[200100];

   map<long long, long long> mp;

   unionfind g;

   cin >> n >> m;

   g.init(n);

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

       cin >> a[i] >> b[i];

       g.unite(a[i], b[i]);

   }



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

      mp[g.find(i)]++;

   }

   for(auto x : mp){

       ans=max(ans, x.second);

   }

   cout << ans <<endl;



   return 0;

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

using namespace std;

//NOT TO SUBMIT IN WRONG PLACE OR BY WRONG COMPILER

//ABC 177, task a, 2020/08/29

//ms,

/*

添え字が1-indexになってるのに気づいてなくて草。

入力時に1小さいものをとるか、最初に配列を一つ大きくとるか。

*/



int main(void){

  int N, M;

  vector<vector<int>> friends(200000);

  queue<int> next;

  vector<int> dist(200000, -1);

  int ans=1;

  int group_size;



  cin >>N >>M;



  //input

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

    int u, v;

    cin >>u >>v;

    friends[u-1].push_back(v-1);

    friends[v-1].push_back(u-1);

  }



  //bfs

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

    if(dist[v] != -1) continue;



    dist[v]=0;

    next.push(v);

    group_size=1;



    while(next.size()!=0){

      int u = next.front();

      next.pop();



      for(long unsigned int i=0;i<friends[u].size();i++){

        int w = friends[u][i];

        if(dist[w] != -1) continue;



        dist[w] = dist[u]+1;

        next.push(w);

        group_size++;

      }

    }//end while

    ans = max(ans, group_size);

  }//end for



  cout <<ans<<endl;

  return 0;

}

/*

お手上げ！！！

解法はunion find木とBFSの二通り。

BFSは連結な重みなしのグラフの最短路問題を線形時間で解けるのが特徴。

また、未探索の頂点が消えるまでやり続ければ連結成分の様子がなんでもわかる。

今回は後者の特徴を使う。

友達のネットワークのグラフの、最大の連結成分の成分個のグループがあればよい。

*/


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

using namespace std;

//NOT TO SUBMIT IN WRONG PLACE OR BY WRONG COMPILER

//ABC 177, task a, 2020/08/30

//ms,

/*

*/



struct UnionFind{

  //各頂点の親のid。親がいないなら、子の頂点数に-1をかけた値。このvectorで木を表現。

  vector<int> r;



  //コンストラクタ

  UnionFind(int N){

    r = vector<int>(N, -1);

  }



  //入力：頂点ラベル。出力：最上位の親id。入力自身でもありうる。ついでにグラフの縮約も。

  int root(int v){

    if(r[v]<0) return v;

    else{

      r[v]=root(r[v]);

      return r[v];

    }

  }



  //入力：二つの頂点ラベル。出力：併合可否。(もともと同じ集合ならfalse)。

  //入力の頂点についてはグラフの縮約をする。さらにそれぞれの頂点の集合を併合する。

  bool unite(int x, int y){

    x=root(x);

    y=root(y);

    //すでに同所属

    if(x==y) return false;



    //異所属の場合、併合。小さい方を大きい方に入れる(これは大事)

    if(abs(r[x]) < abs(r[y]) ) swap(x, y);

    r[x] += r[y];

    r[y] = x;

    return true;

  }



  int size(int x){

    return -r[root(x)];

  }

};



int main(void){

  int N, M;

  int ans=1;



  cin >>N >>M;

  UnionFind friends(N);

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

    int a, b;

    cin >>a >>b;

    friends.unite(a-1, b-1);

  }



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

    ans = max(ans, friends.size(i));

  }



  cout <<ans<<endl;

  return 0;

}

/*

幅優先探索だけじゃなくて、ユニオンファインド木もやるよー。

ユニオンファインド木はグループわけを表現できます。

所属判定も当然できます。超高速で、logNよりさらに速いです(適切な実装のもと)。

グループの大きさも返せます。

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

using namespace std;

//NOT TO SUBMIT IN WRONG PLACE OR BY WRONG COMPILER

//ABC 177, task a, 2020/08/29

//ms,

/*

添え字が1-indexになってるのに気づいてなくて草。

入力時に1小さいものをとるか、最初に配列を一つ大きくとるか。

*/



int main(void){

  int N, M;

  vector<vector<int>> friends(200001);

  queue<int> next;

  vector<int> dist(200001, -1);

  int ans=1;

  int group_size;



  cin >>N >>M;



  //input

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

    int u, v;

    cin >>u >>v;

    friends[u].push_back(v);

    friends[v].push_back(u);

  }



  //bfs

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

    if(dist[v] != -1) continue;



    dist[v]=0;

    next.push(v);

    group_size=1;



    while(next.size()!=0){

      int u = next.front();

      next.pop();



      for(long unsigned int i=0;i<friends[u].size();i++){

        int w = friends[u][i];

        if(dist[w] != -1) continue;



        dist[w] = dist[u]+1;

        next.push(w);

        group_size++;

      }

    }//end while

    ans = max(ans, group_size);

  }//end for



  cout <<ans<<endl;

  return 0;

}

/*

お手上げ！！！

解法はunion find木とBFSの二通り。

BFSは連結な重みなしのグラフの最短路問題を線形時間で解けるのが特徴。

また、未探索の頂点が消えるまでやり続ければ連結成分の様子がなんでもわかる。

今回は後者の特徴を使う。

友達のネットワークのグラフの、最大の連結成分の成分個のグループがあればよい。

*/


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

using namespace std;

//NOT TO SUBMIT IN WRONG PLACE OR BY WRONG COMPILER

//ABC 177, task a, 2020/08/30

//ms,

/*

*/



struct UnionFind{

  //各頂点の親のid。親がいないなら、子の頂点数に-1をかけた値。このvectorで木を表現。

  vector<int> r;



  //コンストラクタ

  UnionFind(int N){

    r = vector<int>(N, -1);

  }



  //入力：頂点ラベル。出力：最上位の親id。入力自身でもありうる。ついでにグラフの縮約も。

  int root(int v){

    if(r[v]<0) return v;

    else{

      r[v]=root(r[v]);

      return r[v];

    }

  }



  //入力：二つの頂点ラベル。出力：併合可否。(もともと同じ集合ならfalse)。

  //入力の頂点についてはグラフの縮約をする。さらにそれぞれの頂点の集合を併合する。

  bool unite(int x, int y){

    x=root(x);

    y=root(y);

    //すでに同所属

    if(x==y) return false;



    //異所属の場合、併合。小さい方を大きい方に入れる(これは大事)

    if(abs(r[x]) < abs(r[y]) ) swap(x, y);

    r[x] += r[y];

    r[y] = x;

    return true;

  }



  int size(int x){

    return -r[root(x)];

  }

};



int main(void){

  int N, M;

  int ans=1;



  cin >>N >>M;

  UnionFind friends(N);

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

    int a, b;

    cin >>a >>b;

    friends.unite(a-1, b-1);

  }



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

    ans = max(ans, friends.size(i));

  }



  cout <<ans<<endl;

  return 0;

}

/*

幅優先探索だけじゃなくて、ユニオンファインド木もやるよー。

ユニオンファインド木はグループわけを表現できます。

所属判定も当然できます。超高速で、logNよりさらに速いです(適切な実装のもと)。

グループの大きさも返せます。

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



using namespace std;



#define MAXN 200005



int N, M;

int cnt;

vector<int> adj[MAXN];

vector<bool> visited;



void dfs(int v)

{

    if (visited[v])

        return;

    

    visited[v] = true;

    cnt++;

    for (auto u : adj[v])

        dfs(u);

}



int main()

{

    cin >> N >> M;

    visited.assign(N + 1, false);

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

        int a, b;

        cin >> a >> b;

        adj[a].push_back(b);

        adj[b].push_back(a);

    }

    int ans = 0;

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

        cnt = 0;

        dfs(i);

        ans = max(ans, cnt);

    }

    cout << ans << '\n';

    return 0;

}

// Faster C++ solution for the same problem (measured speedup: 6.411832128268656x):
#include <iostream>

#include <vector>

#include <set>



using namespace std;



#define MAXN 200005



int N, M;

vector<int> parent;

vector<int> sz;



void init()

{

    parent.assign(N+1, 1);

    sz.assign(N+1, 1);

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

        parent[i] = i;

    }

}



int find(int v)

{

    if (parent[v] == v)

        return v;

    

    return find(parent[v]);

}



bool same(int u, int v)

{

    return find(u) == find(v);

}



void join(int u, int v)

{

    u = find(u);

    v = find(v);

    

    if (u == v)

        return;

    

    if (sz[u] > sz[v])

        swap(u, v);

    

    parent[u] = v;

    sz[v] += sz[u];

}



int main()

{

    cin >> N >> M;

    init();

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

        int a, b;

        cin >> a >> b;

        join(a, b);

    }

    set<int, greater<int> > s;

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

        s.insert(sz[i]);

    }

    cout << *s.begin() << '\n';

    return 0;

}
// Slower C++ solution:
//写経　おぶ　すぬけ

#include <bits/stdc++.h>

using namespace std;



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

struct UnionFind {

	vector<int> d;

	UnionFind(int n=0): d(n,-1) {} //このコロンってなんですか

	int find(int x){

		if (d[x] < 0) return x; //x:根

		return d[x] = find(d[x]);//x:子 -> xの親の根を返す

	}

	bool unite(int x, int y) {

		x = find(x); y = find(y);//根同士をくっつける。

		if ( x ==  y) return false ; 

		/*連結成分が一致してるんだったらfalse返す。

			minimum spanning tree (クラスカル法と言うのをやるときに、くっつけたかどうかを取れると嬉しい.

			chmin/chmaxみたいなノリかな

		 */

		if ( d[x] > d[y]) swap(x,y);//xの方が大きいようにする（ただしサイズは負デモっているので不等号が逆）

		d[x] += d[y] ; //xにyをくっつける.

		d[y] = x;

		return true; 

	}

	bool same(int x, int y) { return find(x) == find(y) ; }

	int size(int x) { return -d[find(x)];}

};



int deg[100005];

vector<int> to[100005] ;

int main(){

	int n, m;

	cin >>  n>> m;



	UnionFind uf(n);

	rep(i,m){

		int a, b;

		cin >>  a>> b;

		uf.unite(a,b);

	}

	int ans = 0;

	rep(i,n){

		ans = max(ans, uf.size(i));

	}

	cout << ans << endl;

}






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



using namespace std;

using ll =long long;

typedef pair<int,int> P;

#define SORT(a) sort((a).begin(),(a).end())

#define REV(a) reverse((a).begin(),(a).end())

#define For(i, a, b)    for(int i = (a) ; i < (b) ; ++i)

#define rep(i, n)       For(i, 0, n)

#define debug(x)  cerr << #x << " = " << (x) << endl;

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

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



void coY() {cout <<"Yes"<<endl;}

void coN(){cout <<"No"<<endl;}

 

//Write From this Line



//const ll mod = 1e9+7;

//const ll mod = 998244353;

//AtCoder解説動画(https://www.youtube.com/watch?v=TdR816rqc3s&feature=youtu.be)からもらった

// (https://atcoder.jp/contests/abc157/submissions/10472433)

struct UnionFind {

	vector<int> d;

	UnionFind(int n=0): d(n,-1) {} //このコロンってなんですか

	int find(int x){

		if (d[x] < 0) return x; //x:根

		return d[x] = find(d[x]);//x:子 -> xの親の根を返す

	}

	bool unite(int x, int y) {

		x = find(x); y = find(y);//根同士をくっつける。

		if ( x ==  y) return false ; 

		/*連結成分が一致してるんだったらfalse返す。

			minimum spanning tree (クラスカル法と言うのをやるときに、くっつけたかどうかを取れると嬉しい.

			chmin/chmaxみたいなノリかな

		 */

		if ( d[x] > d[y]) swap(x,y);//xの方が大きいようにする（ただしサイズは負デモっているので不等号が逆）

		d[x] += d[y] ; //xにyをくっつける.

		d[y] = x;

		return true; 

	}

	bool same(int x, int y) { return find(x) == find(y) ; }

	int size(int x) { return -d[find(x)];}

};

int main()

{

	int n, m;

	cin >> n >> m;

	UnionFind uf(n);

	rep(i,m){

		int a, b;

		cin >> a >> b;

		uf.unite(a,b);

	}

	int ans = 0;

	rep(i,n){

		ans = max(ans,uf.size(i));

	}

	cout << ans << endl;

}
// Slower C++ solution:
#include "bits/stdc++.h"

using namespace std;



const int N=2e5+20;



int n,m,u,v,cnt,ans;

vector <int> adj[N];

set <pair <int,int>> s;

bool vis[N];



void dfs(int node)

{

	cnt++;

	vis[node]=true;

	for(auto child:adj[node])

		if(not vis[child]) dfs(child);

}



int main()

{

	scanf("%d%d",&n,&m);

	while(m--)

	{

		scanf("%d%d",&u,&v);



		if(u>v) swap(u,v);

		if(s.find({u,v})!=s.end()) continue;



		adj[u].push_back(v);

		adj[v].push_back(u);

		s.insert({u,v});

	}



	for(int i=1;i<=n;i++)

	{

		if(vis[i]) continue;

		cnt=0;

		dfs(i);

		ans=max(ans,cnt);

	}



	printf("%d",ans);

}

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

using namespace std;



const int N=2e5+20;

int n,m,u,v,p[N],sz[N],ans;



void init() {for(int i=1;i<=n;i++) p[i]=i,sz[i]=1;}



int root(int i) {return p[i]==i?i:p[i]=root(p[i]);}



bool cycle(int a,int b) {return root(a)==root(b);}



void join(int a,int b)

{

	a=root(a),b=root(b);

	if(sz[a]<sz[b]) swap(a,b);

	p[b]=p[a],sz[a]+=sz[b];

}



int main()

{

	scanf("%d%d",&n,&m);



	init();

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

	{

		scanf("%d%d",&u,&v);

		if(not cycle(u,v)) join(u,v);

	}



	for(int i=1;i<=n;i++) ans=max(ans,sz[root(i)]);

	cout<<ans;

}