#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> 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); } } // Do a DFS to make a tree out of g. dfs2(0, -1); assert(special.size() == k); 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; } } ans = max(ans, dfs(0).second); end:; m2 = (m2-1)&m; } while(m2!=m); } cout << ans << endl; }