// CANONICAL #include #include #include #include using namespace std; struct UnionFind { vector par, rank, size; int c; UnionFind(int n) : par(n), rank(n,0), size(n,1), c(n) { for (int i = 0; i < n; ++i) par[i] = i; } int find(int i) { return (par[i] == i ? i : (par[i] = find(par[i]))); } bool same(int i, int j) { return find(i) == find(j); } int get_size(int i) { return size[find(i)]; } int count() { return c; } int merge(int i, int j) { if ((i = find(i)) == (j = find(j))) return -1; else --c; if (rank[i] > rank[j]) swap(i, j); par[i] = j; size[j] += size[i]; if (rank[i] == rank[j]) rank[j]++; return j; } }; pair dfs(int u, int p, const vector> &g, const vector& off){ int f = 0, t = 1; for(auto v : g[u]){ if(v == p) continue; auto [f2, t2] = dfs(v, u, g, off); f += t2; t += f2; } if(off[u]) t = f; else t = max(t, f); return {f, t}; } int main(){ int n, m; cin >> n >> m; int k = m - n + 1; vector> g(n); UnionFind uf(n); vector> special; for(int i = 0; i < m; ++i){ int u, v; cin >> u >> v; --u, --v; if(uf.same(u, v)) special.push_back({u, v}); else{ g[u].push_back(v); g[v].push_back(u); uf.merge(u, v); } } assert(special.size() == k); int ans = 0; for(size_t m = 0; m < (1< off(n, false); for(int i = 0; i < k; ++i) off[special[i][(m>>i)&1]] = true; ans = max(ans, dfs(0, -1, g, off).second); } cout << ans << endl; }