#include #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; } }; vector> g, tree; vector off, on; pair dfs(int u){ int f = 0, t = 1; assert(!(off[u] and on[u])); if(off[u]) t = -1e6; if(on[u]) f = -1e6; for(auto v : tree[u]){ auto [f2, t2] = dfs(v); f += t2; t += f2; } if(off[u]) t = f; else t = max(t, f); return {f, t}; } void dfs2(int u, int p){ tree[u].reserve(g[u].size()); for(auto v : g[u]){ if(v == p) continue; tree[u].push_back(v); dfs2(v, u); } } int main(){ int n, m; cin >> n >> m; int k = m - n + 1; g.resize(n); tree.resize(n); UnionFind uf(n); vector> edges(m), special; vector special_vertex(n, false); for(auto&x : edges) cin >> x[0] >> x[1]; random_shuffle(begin(edges), end(edges)); for(auto e : edges){ auto u = e[0], v=e[1]; --u, --v; if(uf.same(u, v)){ special.push_back({u, v}); special_vertex[u] = true; special_vertex[v] = true; } else { g[u].push_back(v); g[v].push_back(u); uf.merge(u, v); } } // Do a DFS to make a tree out of g. dfs2(0, -1); assert(special.size() == k); vector> extra_edges; for(int u = 0; u < n; ++u) if(special_vertex[u]) for(auto v : tree[u]) if(special_vertex[v]) extra_edges.push_back({u, v}); int ans = 0; off.assign(n, false); on.assign(n, false); for(size_t m = 0; m < (1<>i)&1){ auto [u, v] = special[i]; if((m2>>i)&1) swap(u, v); if(on[u] or off[v]) goto end; off[u] = true; on[v] = true; } else { auto [u, v] = special[i]; if(on[u] or on[v]) goto end; off[u] = true; off[v] = true; } } for(auto [u, v] : extra_edges) if(on[u] and on[v]) goto end; ans = max(ans, dfs(0).second); end:; m2 = (m2-1)&m; } while(m2!=m); } cout << ans << endl; }