#include<bits/stdc++.h>

using namespace std;

struct UnionFind
{
  vector< int > data;

  UnionFind(int sz)
  {
    data.assign(sz, -1);
  }

  bool unite(int x, int y)
  {
    x = find(x), y = find(y);
    if(x == y) return (false);
    if(data[x] > data[y]) swap(x, y);
    data[x] += data[y];
    data[y] = x;
    return (true);
  }

  int find(int k)
  {
    if(data[k] < 0) return (k);
    return (data[k] = find(data[k]));
  }

  int size(int k)
  {
    return (-data[find(k)]);
  }
};

struct LowLink
{
  UnionFind uf;
  vector< vector< int > > g;
  vector< int > used, ord, low, parent;

  LowLink(size_t v) : g(v), used(v, 0), ord(v), low(v), uf(v), parent(v, -1) {}

  virtual void add_edge(int x, int y)
  {
    g[x].push_back(y);
    g[y].push_back(x);
  }

  void dfs(int idx, int &k, int par = -1)
  {
    used[idx] = true;
    ord[idx] = k++;
    low[idx] = ord[idx];

    for(auto &to : g[idx]) {
      if(!used[to]) {
        dfs(to, k, idx);
        low[idx] = min(low[idx], low[to]);
        parent[to] = idx;
        if(ord[idx] >= low[to]) uf.unite(idx, to);
      } else if(to != par) {
        low[idx] = min(low[idx], ord[to]);
      }
    }
  }

  void dfs()
  {
    int k = 0;
    for(int i = 0; i < g.size(); i++) {
      if(used[i]) continue;
      dfs(i, k);
    }
  }
};

struct BiConnectedComponents : LowLink
{
  vector< pair< int, int > > edges;
  vector< int > comp;

  BiConnectedComponents(size_t v) : LowLink(v), comp(v) {}

  void add_edge(int x, int y)
  {
    LowLink::add_edge(x, y);
    edges.push_back(minmax(x, y));
  }

  int operator[](int k)
  {
    return (comp[k]);
  }

  vector< pair< int, int > > build(vector< vector< int > > &t)
  {
    LowLink::dfs();
    int ptr = 0;
    vector< int > cc(g.size());
    for(int i = 0; i < g.size(); i++) {
      if(i == uf.find(i)) cc[i] = ptr++;
    }

    t.resize(ptr);
    for(int i = 0; i < g.size(); i++) {
      comp[i] = cc[uf.find(i)];
    }
    vector< pair< int, int > > vs;
    for(auto &e : edges) {
      int x = comp[e.first], y = comp[e.second];
      if(x == y) continue;
      vs.emplace_back(e.first, e.second);
      t[x].push_back(y);
      t[y].push_back(x);
    }
    sort(begin(vs), end(vs));
    return (vs);
  }
};

vector< vector< int > > g;
int sz[100000];
int dp[2][100000];

void dfs(int idx, int par)
{
  dp[0][idx] = 0;
  dp[1][idx] = sz[idx];
  for(auto &to : g[idx]) {
    if(to == par) continue;
    dfs(to, idx);
    dp[0][idx] += max(dp[0][to], dp[1][to]);
    dp[1][idx] += dp[0][to];
  }
}

int main()
{
  int N, M;
  scanf("%d %d", &N, &M);
  BiConnectedComponents graph(N);
  for(int i = 0; i < M; i++) {
    int a, b;
    scanf("%d %d", &a, &b);
    graph.add_edge(a, b);
  }
  graph.build(g);

  for(int i = 0; i < N; i++) ++sz[graph[i]];
  int ret = 0;

  memset(dp, -1, sizeof(dp));
  for(int i = 0; i < g.size(); i++) {
    if(~dp[0][i]) continue;
    dfs(i, -1);
    ret += max(dp[0][i], dp[1][i]);
  }
  printf("%d\n", ret);
}