Problem:
"Even" Division
If you talk about an even division in the usual sense of the words, it means dividing a thing
equally. Today, you need to think about something different. A graph is to be divided into
subgraphs with their numbers of nodes being even, that is, multiples of two.
You are given an undirected connected graph with even number of nodes. The given graph is to
be divided into its subgraphs so that all the subgraphs are connected and with even number of
nodes, until no further such division is possible. Figure I.1 illustrates an example. The original
graph of 8 nodes is divided into subgraphs with 4, 2, and 2 nodes. All of them have
even
numbers
of nodes.
Figure I.1. Example of a division (Sample Input/Output 1)
To put it mathematically, an
even
division of a graph is the set of subsets $V_1,\cdot, V_k$ of the graph
nodes satisfying the following conditions.
$V_1 \cup \cdot \cup V_k$ is the set of all the nodes of the input graph, and $V_i \cap Vj = \emptyset$ if $i \neq j$.
Each $V_i$ is non-empty, and has an even number of elements.
Each $V_i$ induces a connected subgraph. In other words, any nodes in $V_i$ are reachable from
        each other by using only the edges of the input graph connecting two nodes in $V_i$.
There is no further division. For any $U_1 \cup U_2 = V_i$, the division obtained by replacing $V_i$
        with the two sets, $U_1$ and $U_2$, does not satisfy either of the conditions 1, 2, or 3.
Your task is to find an
even
division of the given graph.
Input
The input consists of a single test case of the following format.
$n$ $m$
$x_1$ $y_1$
$\vdots$
$x_m$ $y_m$
The first line consists of two integers n and m. The first integer $n$ ($2 \leq n \leq 10^5$) is an even
number representing the number of the nodes of the graph to be divided. The second integer $m$
($n - 1 \leq m \leq 10^5$) is the number of the edges of the graph.
The nodes of the graph are numbered from $0$ to $n - 1$.
The subsequent m lines represent the edges of the graph. A line $x_i y_i$ ($0 \leq xi \lt yi \lt n$) means
that there is an edge connecting the two nodes $x_i$ and $y_i$. There are no duplicated edges. The
input graph is guaranteed to be connected.
Output
If there exists an
even
division of the node set of the given graph into subsets $V_1, \cdots , V_k$, print $k$
in the first line of the output. The next $k$ lines should describe the subsets $V_1, \cdots , V_k$. The order
of the subsets does not matter. The $i$-th of them should begin with the size of $V_i$, followed by
the node numbers of the elements of $V_i$, separated by a space. The order of the node numbers
does not matter either.
If there are multiple even divisions, any of them are acceptable.
Sample Input 1
8 9
0 1
1 2
2 3
0 4
1 6
3 7
4 5
5 6
6 7
Sample Output 1
3
2 3 7
2 4 5
4 0 1 2 6
Sample Input 2
2 1
0 1
Sample Output 2
1
2 0 1
In the Sample 2, the singleton set of the set of the nodes of the original graph is already an even
division.

Submitted solutions:

code_snippet: #include <iostream>
#include <vector>
#include <algorithm>
#include <utility>
using namespace std;

using ll = long long;
#define rep(i,n) for(ll i=0; i<ll(n); i++)


void testcase(){
    int N, M; cin >> N >> M;
    vector<vector<int>> adj(N);
    rep(i,M){
        int u,v; cin >> u >> v;
        adj[u].push_back(v);
        adj[v].push_back(u);
    }
    vector<int> par(N, -1);
    vector<int> gr(N, -1);
    vector<vector<int>> ch(N);
    vector<int> vis(N);

    vector<vector<int>> ans;
    auto re = [&](int s){
        vector<int> bfs; bfs.push_back(s);
        gr[s] = 1;
        rep(i,bfs.size()){
            int v = bfs[i];
            for(int w : ch[v]) if(gr[w] == -1){
                bfs.push_back(w);
                gr[w] = 1;
            }
        }
        ans.push_back(move(bfs));
    };

    auto dfs = [&](auto& dfs, int v) -> int {
        vis[v] = 1;
        int sz = 1;
        for(int w : adj[v]){
            if(vis[w] == 1) continue;
            if(vis[w] == 2 && gr[w] == -1){
                int pre = w;
                for(int t=par[w]; gr[t]==-1 && t!=v; ){
                    for(auto& c : ch[t]) if(c == pre) c = t;
                    re(t);
                    pre = t; t = par[t];
                }
                ch[v].push_back(w); par[w] = v;
                continue;
            }
            if(vis[w] == 0){
                int wsz = dfs(dfs, w);
                ch[v].push_back(w);
                par[w] = v;
                sz += wsz;
            }
        }
        vis[v] = 2;
        if(sz % 2 == 0) re(v);
        return sz;
    };
    dfs(dfs, 0);
    cout << ans.size() << "\n";
    for(auto& a : ans){
        cout << a.size();
        for(int v : a) cout << " " << v;
        cout << "\n";
    }
}

int main(){
    cin.tie(0)->sync_with_stdio(0);
    testcase();
    return 0;
}
accuracy: 1
time_ms: 20
memory_kb: 30800
final_rank: 1

code_snippet: #include<bits/stdc++.h>
using namespace std;
int n,m,x,y;
vector<vector<int>>g;
vector<vector<int>>res;int k;
vector<vector<int>>grp;vector<int>l;
vector<bool>vis;
void dfs(int v){
  vis[v]=true;
  for(int i:g[v]){
    if(vis[i])continue;
    dfs(i);
    // merge
    if(grp[l[v]].size()<grp[l[i]].size()){
      for(int j:grp[l[v]]){
        grp[l[i]].push_back(j);
      }
      l[v]=l[i];
    }else{
      for(int j:grp[l[i]]){
        grp[l[v]].push_back(j);
      }
      l[i]=l[v];
    }
  }
  if(!(grp[v].size()&1L)){
    for(int i:grp[v])res[k].push_back(i);
    grp[v].clear();k++;
  }
  return;
}
int main(){
  cin.tie(0)->sync_with_stdio(0);
  cin>>n>>m;g.resize(n);res.resize(n);vis.resize(n);
  grp.resize(n);l.resize(n);
  for(int i=0;i<n;i++){grp[i].push_back(i);l[i]=i;}
  for(int i=0;i<m;i++){
    cin>>x>>y;g[x].push_back(y);g[y].push_back(x);
  }
  dfs(0);
  cout<<k<<'\n';
  for(int i=0;i<k;i++){
    cout<<res[i].size();
    for(int j:res[i]){
      cout<<' '<<j;
    }
    cout<<'\n';
  }
}
accuracy: 0.04878048780487805
time_ms: 20
memory_kb: 24704
final_rank: 18

code_snippet: #include<bits/stdc++.h>
using namespace std;
int n,m,x,y;
vector<vector<int>>g;
vector<vector<int>>res;int k;
vector<bool>vis;
void dfs(int v){
  vis[v]=true;
  for(int i:g[v]){
    if(vis[i])continue;
    dfs(i);
  }
  res[k].push_back(v);
  if(!(res[k].size()&1L))k++;
  return;
}
int main(){
  cin.tie(0)->sync_with_stdio(0);
  cin>>n>>m;g.resize(n);res.resize(n);vis.resize(n);
  for(int i=0;i<m;i++){
    cin>>x>>y;g[x].push_back(y);g[y].push_back(x);
  }
  dfs(0);
  cout<<k<<'\n';
  for(int i=0;i<k;i++){
    cout<<res[i].size();
    for(int j:res[i]){
      cout<<' '<<j;
    }
    cout<<"\n";
  }
}
accuracy: 0.04878048780487805
time_ms: 20
memory_kb: 15336
final_rank: 17

code_snippet: #include <bits/stdc++.h>
using namespace std;

#define foa(s, v) for(auto& s : v)
#define rng(i, l, r) for(int i = int(l); i < int(r); i++)
#define rep(i, n) rng(i, 0, n)
#define sz(x) int(x.size())
#define all(x) begin(x), end(x)

template <class T>
bool chmax(T& a, T b) {
	return a < b ? a = b, true : false;
}
template <class T>
bool chmin(T& a, T b) {
	return a > b ? a = b, true : false;
}
using ll = long long;
using vi = vector<int>;


#ifdef LOCAL
#define debug(x) cerr << __LINE__ << ", " << #x << ": " << x << "\n"
#else
#define debug(x) (void(0))
#endif

template <class T>
ostream& operator<<(ostream& os, vector<T> v) {
	os << "{ ";
	foa(t, v) os << t << ", ";
	os << "}";
	return os;
}

using ll = long long;

int n;
void solve() {
	int m;
	cin >> m;
	vector<vector<int>> g(n);

	rep(j, m) {
		int a, b;
		cin >> a >> b;
		g[a].push_back(b);
		g[b].push_back(a);
	}

	vector<vi> child(n), upward(n), jump(n);

	const int rt = 0;

	vector<vector<int>> ans;
	vector<int> ord(n, -1);

	int cur_ord = 0;

	auto dfs = [&](auto self, int cur, int par) -> void {
		ord[cur] = cur_ord++;
		foa(adj, g[cur]) {
			if(ord[adj] == -1) {
				child[cur].push_back(adj);
				self(self, adj, cur);
			} else if(adj != par && ord[adj] < ord[cur]) {
				upward[cur].push_back(adj);
			}
		}
		sort(all(upward[cur]), [&](int u, int v) -> bool { return ord[u] < ord[v]; });
	};

	dfs(dfs, rt, -1);

	debug(child);
	debug(upward);

	vector<int> added(n, 0);

	auto paint = [&](int x) -> bool {
		if(added[x]) return false;
		added[x] = 1;
		ans.back().push_back(x);
		return true;
	};

	auto append_ans = [&](auto self, int cur) -> void {
		if(!paint(cur)) return;
		foa(c, child[cur]) { self(self, c); }
		foa(c, jump[cur]) { self(self, c); }
	};

	// subvertex id
	auto f = [&](auto self, int cur) -> int {
		vector<int> real_child;

		foa(ch_virtual, child[cur]) {
			const int c = self(self, ch_virtual);
			if(c < 0) continue;
			real_child.push_back(c);
		}

		foa(x, jump[cur]) { real_child.push_back(x); }

		if(sz(real_child) % 2 == 1) {
			ans.push_back({});
			paint(cur);
			foa(r, real_child) append_ans(append_ans, r);
			return -1;
		}

		auto find_jump = [&]() -> int {
			foa(r, real_child) {
				if(sz(upward[r])) return r;
			}
			return -1;
		};

		int from = find_jump();
		if(from == -1) return cur;

		int up = upward[from].back();
		upward[from].pop_back();
		jump[up].push_back(from);

		ans.push_back({});
		paint(cur);
		foa(r, real_child) if(r != from) append_ans(append_ans, r);
		return -1;
	};

	f(f, rt);

	cout << sz(ans) << '\n';
	foa(v, ans) {
		cout << sz(v);
		foa(x, v) cout << ' ' << x;
		cout << endl;
	}
}

int main() {
	ios::sync_with_stdio(false);
	cin.tie(nullptr);

	while(cin >> n) solve();
}
accuracy: 1
time_ms: 60
memory_kb: 41860
final_rank: 5

code_snippet: #include <bits/stdc++.h>
using namespace std;

#define foa(s, v) for(auto& s : v)
#define rng(i, l, r) for(int i = int(l); i < int(r); i++)
#define rep(i, n) rng(i, 0, n)
#define sz(x) int(x.size())
#define all(x) begin(x), end(x)

template <class T>
bool chmax(T& a, T b) {
	return a < b ? a = b, true : false;
}
template <class T>
bool chmin(T& a, T b) {
	return a > b ? a = b, true : false;
}
using ll = long long;
int n;
using vi = vector<int>;

void solve() {
	int m;
	cin >> m;
	vector<vector<int>> g(n);

	rep(j, m) {
		int a, b;
		cin >> a >> b;
		g[a].push_back(b);
		g[b].push_back(a);
	}

	vector<vi> child(n), upward(n), jump(n);

	const int rt = 0;

	vector<vector<int>> ans;
	vector<int> ord(n, -1);

	int cur_ord = 0;

	auto dfs = [&](auto self, int cur, int par) -> void {
		ord[cur] = cur_ord++;
		foa(adj, g[cur]) {
			if(ord[adj] == -1) {
				child[cur].push_back(adj);
				self(self, adj, cur);
			} else if(adj != par) {
				upward[cur].push_back(adj);
			}
		}
		sort(all(upward[cur]), [&](int u, int v) -> bool { return ord[u] < ord[v]; });
	};

	dfs(dfs, rt, -1);

	vector<int> added(n, 0);

	auto paint = [&](int x) -> bool {
		if(added[x]) return false;
		added[x] = 1;
		ans.back().push_back(x);
		return true;
	};

	auto append_ans = [&](auto self, int cur) -> void {
		if(!paint(cur)) return;
		foa(c, child[cur]) { self(self, c); }
	};

	// subvertex id
	auto f = [&](auto self, int cur) -> int {
		vector<int> real_child;

		foa(ch_virtual, child[cur]) {
			const int c = self(self, ch_virtual);
			if(c < 0) continue;
			real_child.push_back(c);
		}

		foa(x, jump[cur]) { real_child.push_back(x); }

		if(sz(real_child) % 2 == 1) {
			ans.push_back({});
			append_ans(append_ans, cur);
			return -1;
		}

		auto find_jump = [&]() -> int {
			foa(r, real_child) {
				if(sz(upward[r])) return r;
			}
			return -1;
		};

		int from = find_jump();
		if(from == -1) return cur;

		int up = upward[from].back();
		upward[from].pop_back();
		jump[up].push_back(from);

		ans.push_back({cur});
		foa(r, real_child) if(r != from) append_ans(append_ans, r);
		return -1;
	};

	f(f, rt);

	cout << sz(ans) << '\n';
	foa(v, ans) {
		cout << sz(v);
		foa(x, v) cout << ' ' << x;
		cout << endl;
	}
}

int main() {
	ios::sync_with_stdio(false);
	cin.tie(nullptr);

	while(cin >> n) solve();
}
accuracy: 0.07317073170731707
time_ms: 60
memory_kb: 39172
final_rank: 16

code_snippet: #include <bits/stdc++.h>
using namespace std;
#if __has_include(<atcoder/all>)
#include <atcoder/all>
using namespace atcoder;
template<int mod>istream &operator>>(istream &is,static_modint<mod> &a){long long b;is>>b;a=b;return is;}
istream &operator>>(istream &is,modint &a){long long b;cin>>b;a=b;return is;}
#endif
#ifdef LOCAL
#include "debug.h"
#else
#define debug(...) static_cast<void>(0)
#define debugg(...) static_cast<void>(0)
#define esper(...) static_cast<void>(0)
template<typename T1,typename T2>ostream &operator<<(ostream &os,const pair<T1,T2>&p){os<<p.first<<' '<<p.second;return os;}
#endif
using ll=long long;
using ull=unsigned long long;
using P=pair<ll,ll>;
template<typename T>using minque=priority_queue<T,vector<T>,greater<T>>;
template<typename T>bool chmax(T &a,const T &b){return (a<b?(a=b,true):false);}
template<typename T>bool chmin(T &a,const T &b){return (a>b?(a=b,true):false);}
template<typename T1,typename T2>istream &operator>>(istream &is,pair<T1,T2>&p){is>>p.first>>p.second;return is;}
template<typename T>istream &operator>>(istream &is,vector<T> &a){for(auto &i:a)is>>i;return is;}
template<typename T1,typename T2>void operator++(pair<T1,T2>&a,int n){a.first++,a.second++;}
template<typename T1,typename T2>void operator--(pair<T1,T2>&a,int n){a.first--,a.second--;}
template<typename T>void operator++(vector<T>&a,int n){for(auto &i:a)i++;}
template<typename T>void operator--(vector<T>&a,int n){for(auto &i:a)i--;}
#define reps(i,a,n) for(int i=(a);i<(n);i++)
#define rep(i,n) reps(i,0,n)
#define all(x) x.begin(),x.end()
#define pcnt(x) __builtin_popcountll(x)
#define fin(x) return cout<<x<<'\n',static_cast<void>(0)
ll myceil(ll a,ll b){return (a+b-1)/b;}
template<typename T,size_t n,size_t id=0>
auto vec(const int (&d)[n],const T &init=T()){
  if constexpr (id<n)return vector(d[id],vec<T,n,id+1>(d,init));
  else return init;
}
void SOLVE();
int main(){
  ios::sync_with_stdio(false);
  cin.tie(nullptr);
  cout<<fixed<<setprecision(16);
  #ifdef LOCAL
  clock_t start=clock();
  #endif
  int testcase=1;
  //cin>>testcase;
  for(int i=0;i<testcase;i++){
    SOLVE();
  }
  #ifdef LOCAL
  cerr<<"time:";
  cerr<<(clock()-start)/1000;
  cerr<<"ms\n";
  #endif
}
struct UF{
  vector<int>par;
  UF(int n):par(n,-1){}
  int root(int u){
    if(par[u]<0)return u;
    return par[u]=root(par[u]);
  }
  void merge(int u,int v){
    int ru=root(u),rv=root(v);
    if(ru!=rv){
      par[ru]+=par[rv];
      par[rv]=ru;
    }
  }
  bool same(int u,int v){return root(u)==root(v);}
};
int n,m;
vector<vector<int>>to;
mt19937 mt(998244353);
vector<vector<int>>decomp(vector<int>id,int dep){
  debug(id,dep);
  int root=mt()%id.size();
  vector<vector<int>>g(id.size());
  auto add=[&](int u,int v){
    u=lower_bound(all(id),u)-id.begin();
    v=lower_bound(all(id),v)-id.begin();
    g[u].push_back(v);
    g[v].push_back(u);
  };
  vector<bool>seen(id.size(),false);
  auto dfs=[&](auto self,int x)->void {
    seen[lower_bound(all(id),x)-id.begin()]=true;
    for(auto i:to[x])if(binary_search(all(id),i)&&!seen[lower_bound(all(id),i)-id.begin()]){
      add(x,i);
      self(self,i);
    }
  };
  dfs(dfs,id[root]);
  UF uf(id.size());
  auto dfs2=[&](auto self,int x,int p)->bool {
    bool f=false;
    for(auto i:g[x])if(i!=p){
      if(self(self,i,x)){
        f^=1;
        uf.merge(i,x);
        // uf.merge(lower_bound(all(id),i)-id.begin(),lower_bound(all(id),x)-id.begin());
      }
    }
    return !f;
  };
  assert(!dfs2(dfs2,0,-1));
  vector<int>rot;
  rep(i,id.size())rot.push_back(uf.root(i));
  sort(all(rot)),rot.erase(unique(all(rot)),rot.end());
  vector<vector<int>>ans(rot.size());
  rep(i,id.size())ans[lower_bound(all(rot),uf.root(i))-rot.begin()].push_back(id[i]);
  if(dep>=50)return ans;
  debug(ans);
  vector<vector<int>>ans2;
  for(auto i:ans){
    vector<vector<int>>now=decomp(i,dep+1);
    ans2.insert(ans2.end(),all(now));
    // ans2.insert(ans2.end(),all(decomp(i,dep+1)));
  }
  return ans2;
}
void SOLVE(){
  int n,m;
  cin>>n>>m;
  to.resize(n);
  rep(i,m){
    int u,v;
    cin>>u>>v;
    to[u].push_back(v);
    to[v].push_back(u);
  }
  vector<int>id(n);
  iota(all(id),0);
  vector<vector<int>>ans=decomp(id,0);
  cout<<ans.size()<<endl;
  rep(i,ans.size()){
    cout<<ans[i].size()<<' ';
    rep(j,ans[i].size())cout<<ans[i][j]<<" \n"[j+1==ans[i].size()];
  }
}
accuracy: 1
time_ms: 1350
memory_kb: 218992
final_rank: 8

code_snippet: #include <bits/stdc++.h>
using namespace std;
#if __has_include(<atcoder/all>)
#include <atcoder/all>
using namespace atcoder;
template<int mod>istream &operator>>(istream &is,static_modint<mod> &a){long long b;is>>b;a=b;return is;}
istream &operator>>(istream &is,modint &a){long long b;cin>>b;a=b;return is;}
#endif
#ifdef LOCAL
#include "debug.h"
#else
#define debug(...) static_cast<void>(0)
#define debugg(...) static_cast<void>(0)
#define esper(...) static_cast<void>(0)
template<typename T1,typename T2>ostream &operator<<(ostream &os,const pair<T1,T2>&p){os<<p.first<<' '<<p.second;return os;}
#endif
using ll=long long;
using ull=unsigned long long;
using P=pair<ll,ll>;
template<typename T>using minque=priority_queue<T,vector<T>,greater<T>>;
template<typename T>bool chmax(T &a,const T &b){return (a<b?(a=b,true):false);}
template<typename T>bool chmin(T &a,const T &b){return (a>b?(a=b,true):false);}
template<typename T1,typename T2>istream &operator>>(istream &is,pair<T1,T2>&p){is>>p.first>>p.second;return is;}
template<typename T>istream &operator>>(istream &is,vector<T> &a){for(auto &i:a)is>>i;return is;}
template<typename T1,typename T2>void operator++(pair<T1,T2>&a,int n){a.first++,a.second++;}
template<typename T1,typename T2>void operator--(pair<T1,T2>&a,int n){a.first--,a.second--;}
template<typename T>void operator++(vector<T>&a,int n){for(auto &i:a)i++;}
template<typename T>void operator--(vector<T>&a,int n){for(auto &i:a)i--;}
#define reps(i,a,n) for(int i=(a);i<(n);i++)
#define rep(i,n) reps(i,0,n)
#define all(x) x.begin(),x.end()
#define pcnt(x) __builtin_popcountll(x)
#define fin(x) return cout<<x<<'\n',static_cast<void>(0)
ll myceil(ll a,ll b){return (a+b-1)/b;}
template<typename T,size_t n,size_t id=0>
auto vec(const int (&d)[n],const T &init=T()){
  if constexpr (id<n)return vector(d[id],vec<T,n,id+1>(d,init));
  else return init;
}
void SOLVE();
int main(){
  ios::sync_with_stdio(false);
  cin.tie(nullptr);
  cout<<fixed<<setprecision(16);
  #ifdef LOCAL
  clock_t start=clock();
  #endif
  int testcase=1;
  //cin>>testcase;
  for(int i=0;i<testcase;i++){
    SOLVE();
  }
  #ifdef LOCAL
  cerr<<"time:";
  cerr<<(clock()-start)/1000;
  cerr<<"ms\n";
  #endif
}
struct UF{
  vector<int>par;
  UF(int n):par(n,-1){}
  int root(int u){
    if(par[u]<0)return u;
    return par[u]=root(par[u]);
  }
  void merge(int u,int v){
    int ru=root(u),rv=root(v);
    if(ru!=rv){
      par[ru]+=par[rv];
      par[rv]=ru;
    }
  }
  bool same(int u,int v){return root(u)==root(v);}
};
int n,m;
vector<vector<int>>to;
mt19937 mt(998244353);
vector<vector<int>>decomp(vector<int>id,int dep){
  debug(id,dep);
  int root=mt()%id.size();
  vector<vector<int>>g(id.size());
  auto add=[&](int u,int v){
    u=lower_bound(all(id),u)-id.begin();
    v=lower_bound(all(id),v)-id.begin();
    g[u].push_back(v);
    g[v].push_back(u);
  };
  vector<bool>seen(id.size(),false);
  auto dfs=[&](auto self,int x)->void {
    seen[lower_bound(all(id),x)-id.begin()]=true;
    for(auto i:to[x])if(binary_search(all(id),i)&&!seen[lower_bound(all(id),i)-id.begin()]){
      add(x,i);
      self(self,i);
    }
  };
  dfs(dfs,id[root]);
  UF uf(id.size());
  auto dfs2=[&](auto self,int x,int p)->bool {
    bool f=false;
    for(auto i:g[x])if(i!=p){
      if(self(self,i,x)){
        f^=1;
        uf.merge(i,x);
        // uf.merge(lower_bound(all(id),i)-id.begin(),lower_bound(all(id),x)-id.begin());
      }
    }
    return !f;
  };
  assert(!dfs2(dfs2,0,-1));
  vector<int>rot;
  rep(i,id.size())rot.push_back(uf.root(i));
  sort(all(rot)),rot.erase(unique(all(rot)),rot.end());
  vector<vector<int>>ans(rot.size());
  rep(i,id.size())ans[lower_bound(all(rot),uf.root(i))-rot.begin()].push_back(id[i]);
  if(dep>=10)return ans;
  debug(ans);
  vector<vector<int>>ans2;
  for(auto i:ans){
    vector<vector<int>>now=decomp(i,dep+1);
    ans2.insert(ans2.end(),all(now));
    // ans2.insert(ans2.end(),all(decomp(i,dep+1)));
  }
  return ans2;
}
void SOLVE(){
  int n,m;
  cin>>n>>m;
  to.resize(n);
  rep(i,m){
    int u,v;
    cin>>u>>v;
    to[u].push_back(v);
    to[v].push_back(u);
  }
  vector<int>id(n);
  iota(all(id),0);
  vector<vector<int>>ans=decomp(id,0);
  cout<<ans.size()<<endl;
  rep(i,ans.size()){
    cout<<ans[i].size()<<' ';
    rep(j,ans[i].size())cout<<ans[i][j]<<" \n"[j+1==ans[i].size()];
  }
}
accuracy: 0.5609756097560976
time_ms: 180
memory_kb: 32700
final_rank: 9

code_snippet: #include <bits/stdc++.h>
using namespace std;
#if __has_include(<atcoder/all>)
#include <atcoder/all>
using namespace atcoder;
template<int mod>istream &operator>>(istream &is,static_modint<mod> &a){long long b;is>>b;a=b;return is;}
istream &operator>>(istream &is,modint &a){long long b;cin>>b;a=b;return is;}
#endif
#ifdef LOCAL
#include "debug.h"
#else
#define debug(...) static_cast<void>(0)
#define debugg(...) static_cast<void>(0)
#define esper(...) static_cast<void>(0)
template<typename T1,typename T2>ostream &operator<<(ostream &os,const pair<T1,T2>&p){os<<p.first<<' '<<p.second;return os;}
#endif
using ll=long long;
using ull=unsigned long long;
using P=pair<ll,ll>;
template<typename T>using minque=priority_queue<T,vector<T>,greater<T>>;
template<typename T>bool chmax(T &a,const T &b){return (a<b?(a=b,true):false);}
template<typename T>bool chmin(T &a,const T &b){return (a>b?(a=b,true):false);}
template<typename T1,typename T2>istream &operator>>(istream &is,pair<T1,T2>&p){is>>p.first>>p.second;return is;}
template<typename T>istream &operator>>(istream &is,vector<T> &a){for(auto &i:a)is>>i;return is;}
template<typename T1,typename T2>void operator++(pair<T1,T2>&a,int n){a.first++,a.second++;}
template<typename T1,typename T2>void operator--(pair<T1,T2>&a,int n){a.first--,a.second--;}
template<typename T>void operator++(vector<T>&a,int n){for(auto &i:a)i++;}
template<typename T>void operator--(vector<T>&a,int n){for(auto &i:a)i--;}
#define reps(i,a,n) for(int i=(a);i<(n);i++)
#define rep(i,n) reps(i,0,n)
#define all(x) x.begin(),x.end()
#define pcnt(x) __builtin_popcountll(x)
#define fin(x) return cout<<x<<'\n',static_cast<void>(0)
ll myceil(ll a,ll b){return (a+b-1)/b;}
template<typename T,size_t n,size_t id=0>
auto vec(const int (&d)[n],const T &init=T()){
  if constexpr (id<n)return vector(d[id],vec<T,n,id+1>(d,init));
  else return init;
}
void SOLVE();
int main(){
  ios::sync_with_stdio(false);
  cin.tie(nullptr);
  cout<<fixed<<setprecision(16);
  #ifdef LOCAL
  clock_t start=clock();
  #endif
  int testcase=1;
  //cin>>testcase;
  for(int i=0;i<testcase;i++){
    SOLVE();
  }
  #ifdef LOCAL
  cerr<<"time:";
  cerr<<(clock()-start)/1000;
  cerr<<"ms\n";
  #endif
}
struct UF{
  vector<int>par;
  UF(int n):par(n,-1){}
  int root(int u){
    if(par[u]<0)return u;
    return par[u]=root(par[u]);
  }
  void merge(int u,int v){
    int ru=root(u),rv=root(v);
    if(ru!=rv){
      par[ru]+=par[rv];
      par[rv]=ru;
    }
  }
  bool same(int u,int v){return root(u)==root(v);}
};
int n,m;
vector<vector<int>>to;
mt19937 mt(998244353);
vector<vector<int>>decomp(vector<int>id,int dep){
  debug(id,dep);
  int root=mt()%id.size();
  vector<vector<int>>g(id.size());
  auto add=[&](int u,int v){
    u=lower_bound(all(id),u)-id.begin();
    v=lower_bound(all(id),v)-id.begin();
    g[u].push_back(v);
    g[v].push_back(u);
  };
  vector<bool>seen(id.size(),false);
  auto dfs=[&](auto self,int x)->void {
    seen[lower_bound(all(id),x)-id.begin()]=true;
    for(auto i:to[x])if(binary_search(all(id),i)&&!seen[lower_bound(all(id),i)-id.begin()]){
      add(x,i);
      self(self,i);
    }
  };
  dfs(dfs,id[root]);
  UF uf(id.size());
  auto dfs2=[&](auto self,int x,int p)->bool {
    bool f=false;
    for(auto i:g[x])if(i!=p){
      if(self(self,i,x)){
        f^=1;
        uf.merge(i,x);
        // uf.merge(lower_bound(all(id),i)-id.begin(),lower_bound(all(id),x)-id.begin());
      }
    }
    return !f;
  };
  assert(!dfs2(dfs2,0,-1));
  vector<int>rot;
  rep(i,id.size())rot.push_back(uf.root(i));
  sort(all(rot)),rot.erase(unique(all(rot)),rot.end());
  vector<vector<int>>ans(rot.size());
  rep(i,id.size())ans[lower_bound(all(rot),uf.root(i))-rot.begin()].push_back(id[i]);
  if(dep>=10)return ans;
  if(ans.size()==1)return ans;
  debug(ans);
  vector<vector<int>>ans2;
  for(auto i:ans){
    vector<vector<int>>now=decomp(i,dep+1);
    ans2.insert(ans2.end(),all(now));
    // ans2.insert(ans2.end(),all(decomp(i,dep+1)));
  }
  return ans2;
}
void SOLVE(){
  int n,m;
  cin>>n>>m;
  to.resize(n);
  rep(i,m){
    int u,v;
    cin>>u>>v;
    to[u].push_back(v);
    to[v].push_back(u);
  }
  vector<int>id(n);
  iota(all(id),0);
  vector<vector<int>>ans=decomp(id,0);
  cout<<ans.size()<<endl;
  rep(i,ans.size()){
    cout<<ans[i].size()<<' ';
    rep(j,ans[i].size())cout<<ans[i][j]<<" \n"[j+1==ans[i].size()];
  }
}
accuracy: 0.04878048780487805
time_ms: 60
memory_kb: 32640
final_rank: 19

code_snippet: #include <bits/stdc++.h>
using namespace std;
#if __has_include(<atcoder/all>)
#include <atcoder/all>
using namespace atcoder;
template<int mod>istream &operator>>(istream &is,static_modint<mod> &a){long long b;is>>b;a=b;return is;}
istream &operator>>(istream &is,modint &a){long long b;cin>>b;a=b;return is;}
#endif
#ifdef LOCAL
#include "debug.h"
#else
#define debug(...) static_cast<void>(0)
#define debugg(...) static_cast<void>(0)
#define esper(...) static_cast<void>(0)
template<typename T1,typename T2>ostream &operator<<(ostream &os,const pair<T1,T2>&p){os<<p.first<<' '<<p.second;return os;}
#endif
using ll=long long;
using ull=unsigned long long;
using P=pair<ll,ll>;
template<typename T>using minque=priority_queue<T,vector<T>,greater<T>>;
template<typename T>bool chmax(T &a,const T &b){return (a<b?(a=b,true):false);}
template<typename T>bool chmin(T &a,const T &b){return (a>b?(a=b,true):false);}
template<typename T1,typename T2>istream &operator>>(istream &is,pair<T1,T2>&p){is>>p.first>>p.second;return is;}
template<typename T>istream &operator>>(istream &is,vector<T> &a){for(auto &i:a)is>>i;return is;}
template<typename T1,typename T2>void operator++(pair<T1,T2>&a,int n){a.first++,a.second++;}
template<typename T1,typename T2>void operator--(pair<T1,T2>&a,int n){a.first--,a.second--;}
template<typename T>void operator++(vector<T>&a,int n){for(auto &i:a)i++;}
template<typename T>void operator--(vector<T>&a,int n){for(auto &i:a)i--;}
#define reps(i,a,n) for(int i=(a);i<(n);i++)
#define rep(i,n) reps(i,0,n)
#define all(x) x.begin(),x.end()
#define pcnt(x) __builtin_popcountll(x)
#define fin(x) return cout<<x<<'\n',static_cast<void>(0)
ll myceil(ll a,ll b){return (a+b-1)/b;}
template<typename T,size_t n,size_t id=0>
auto vec(const int (&d)[n],const T &init=T()){
  if constexpr (id<n)return vector(d[id],vec<T,n,id+1>(d,init));
  else return init;
}
void SOLVE();
int main(){
  ios::sync_with_stdio(false);
  cin.tie(nullptr);
  cout<<fixed<<setprecision(16);
  #ifdef LOCAL
  clock_t start=clock();
  #endif
  int testcase=1;
  //cin>>testcase;
  for(int i=0;i<testcase;i++){
    SOLVE();
  }
  #ifdef LOCAL
  cerr<<"time:";
  cerr<<(clock()-start)/1000;
  cerr<<"ms\n";
  #endif
}
struct UF{
  vector<int>par;
  UF(int n):par(n,-1){}
  int root(int u){
    if(par[u]<0)return u;
    return par[u]=root(par[u]);
  }
  void merge(int u,int v){
    int ru=root(u),rv=root(v);
    if(ru!=rv){
      par[ru]+=par[rv];
      par[rv]=ru;
    }
  }
  bool same(int u,int v){return root(u)==root(v);}
};
void SOLVE(){
  int n,m;
  cin>>n>>m;
  vector<vector<int>>to(n);
  rep(i,m){
    int u,v;
    cin>>u>>v;
    to[u].push_back(v);
    to[v].push_back(u);
  }
  vector<vector<int>>g(n);
  vector<int>cnt(n,0);
  auto add=[&](int u,int v){
    g[u].push_back(v);
    g[v].push_back(u);
    cnt[u]++,cnt[v]++;
  };
  vector<bool>seen(n,false);
  auto dfs=[&](auto self,int x)->void {
    seen[x]=true;
    for(auto i:to[x])if(!seen[i]){
      add(x,i);
      self(self,i);
    }
  };
  dfs(dfs,0);
  UF uf(n);
  auto dfs2=[&](auto self,int x,int p)->bool {
    debug(x,p);
    bool f=false;
    for(auto i:g[x])if(i!=p){
      if(self(self,i,x)){
        f^=1;
        uf.merge(i,x);
      }
    }
    return !f;
  };
  assert(!dfs2(dfs2,0,-1));
  vector<int>rot;
  rep(i,n)rot.push_back(uf.root(i));
  sort(all(rot)),rot.erase(unique(all(rot)),rot.end());
  vector<vector<int>>ans(rot.size());
  rep(i,n)ans[lower_bound(all(rot),uf.root(i))-rot.begin()].push_back(i);
  cout<<ans.size()<<endl;
  rep(i,ans.size()){
    cout<<ans[i].size()<<' ';
    rep(j,ans[i].size())cout<<ans[i][j]<<" \n"[j+1==ans[i].size()];
  }
}
accuracy: 0.2926829268292683
time_ms: 30
memory_kb: 29692
final_rank: 12

code_snippet: #include <iostream>
#include <vector>
#include <tuple>
#include <set>
#include <map>
#include <ctime>
#include <algorithm>
using namespace std;

// First Part
int N, M, X[100009], Y[100009];
int dist[100009], dp[100009], par[100009];
vector<int> G[100009];
vector<int> Current, tmp;

// Second Part
int NumGroup = 0;
int Group[100009];
bool used[100009];
vector<tuple<int, int, int>> List[100009]; // Non-Tree Edges
set<int> H[100009];

void dfs1(int pos, int dep) {
	dist[pos] = dep;
	dp[pos] = 1;
	for (int to : G[pos]) {
		if (dist[to] == -1) {
			Current.push_back(to); dfs1(to, dep + 1); Current.pop_back();
			par[to] = pos;
			dp[pos] += dp[to];
			H[pos].insert(to);
			H[to].insert(pos);
		}
		else {
			if (dist[pos] - dist[to] >= 2) {
				int val = dist[to];
				int nex = Current[val + 1];
				List[to].push_back(make_tuple(dist[pos], nex, pos));
			}
		}
	}
}

void dfs2(int pos, int col) {
	Group[pos] = col;
	used[pos] = true; tmp.push_back(pos);
	auto itr = H[pos].begin();
	while (itr != H[pos].end()) {
		int to = (*itr);
		if (used[to] == false) dfs2(to, col);
		itr++;
	}
}

void FindComponents(int pos, int col) {
	tmp.clear();
	dfs2(pos, col);
	for (int i : tmp) used[i] = false;
}

void DeleteEdge(int u, int v) {
	H[u].erase(v);
	H[v].erase(u);
}

void Delete(int pos) {
	map<int, int> Map;
	sort(List[pos].begin(), List[pos].end());
	
	// Deletion Start
	for (int i = 0; i < (int)List[pos].size(); i++) {
		int idx1 = get<1>(List[pos][i]);
		int idx2 = get<2>(List[pos][i]); if (Group[pos] != Group[idx2]) continue;
		
		// Edge Delete
		pair<int, int> u1 = make_pair(pos, idx1); if (Map[idx1] != 0) u1.second = Map[idx1] - 1;
		pair<int, int> u2 = make_pair(idx2, par[idx2]);
		DeleteEdge(u1.first, u1.second);
		DeleteEdge(u2.first, u2.second);
		H[pos].insert(idx2);
		H[idx2].insert(pos);
		
		// Division
		NumGroup += 1;
		FindComponents(par[idx2], NumGroup);
		Map[idx1] = idx2 + 1;
		par[idx2] = pos;
	}
}

int main() {
	srand((unsigned)time(NULL));
	
	// Input
	cin >> N >> M;
	for (int i = 0; i < M; i++) cin >> X[i] >> Y[i];
	for (int i = 1; i < M; i++) {
		int idx = rand() % (i + 1);
		swap(X[idx], X[i]);
		swap(Y[idx], Y[i]);
	}
	for (int i = 0; i < M; i++) {
		G[X[i]].push_back(Y[i]);
		G[Y[i]].push_back(X[i]);
	}
	
	// Calculate dp[i], par[i], List[i]
	int BOSS = rand() % N;
	for (int i = 0; i < N; i++) par[i] = -1;
	for (int i = 0; i < N; i++) dist[i] = -1;
	Current.push_back(BOSS);
	dfs1(BOSS, 0);
	
	// Split Edges
	for (int i = 0; i < N; i++) {
		if (dp[i] % 2 == 1 || i == BOSS) continue;
		DeleteEdge(i, par[i]);
		par[i] = -1;
	}
	
	// Get Connected Components
	for (int i = 0; i < N; i++) {
		if (Group[i] >= 1) continue;
		NumGroup += 1;
		FindComponents(i, NumGroup);
	}
	
	// Delete Edges
	vector<pair<int, int>> Order;
	for (int i = 0; i < N; i++) Order.push_back(make_pair(dist[i], i));
	sort(Order.begin(), Order.end());
	reverse(Order.begin(), Order.end());
	for (int i = 0; i < (int)Order.size(); i++) {
		Delete(Order[i].second);
	}
	
	// Finalize
	NumGroup = 0;
	for (int i = 0; i < N; i++) Group[i] = -1;
	for (int i = 0; i < N; i++) {
		if (Group[i] >= 1) continue;
		NumGroup += 1;
		FindComponents(i, NumGroup);
	}
	
	// Get Answer
	vector<vector<int>> Answer(NumGroup + 1, vector<int>(0, 0));
	for (int i = 0; i < N; i++) Answer[Group[i]].push_back(i);
	cout << NumGroup << endl;
	for (int i = 1; i <= NumGroup; i++) {
		cout << Answer[i].size();
		for (int j = 0; j < (int)Answer[i].size(); j++) cout << " " << Answer[i][j];
		cout << endl;
	}
	return 0;
}
accuracy: 0.3902439024390244
time_ms: 90
memory_kb: 32748
final_rank: 11

code_snippet: #include <iostream>
#include <vector>
#include <tuple>
#include <set>
#include <map>
#include <algorithm>
using namespace std;

// First Part
int N, M, X[100009], Y[100009];
int dist[100009], dp[100009], par[100009];
vector<int> G[100009];
vector<int> Current, tmp;

// Second Part
int NumGroup = 0;
int Group[100009];
bool used[100009];
vector<tuple<int, int, int>> List[100009]; // Non-Tree Edges
set<int> H[100009];

void dfs1(int pos, int dep) {
	dist[pos] = dep;
	dp[pos] = 1;
	for (int to : G[pos]) {
		if (dist[to] == -1) {
			Current.push_back(to); dfs1(to, dep + 1); Current.pop_back();
			par[to] = pos;
			dp[pos] += dp[to];
			H[pos].insert(to);
			H[to].insert(pos);
		}
		else {
			if (dist[pos] - dist[to] >= 2) {
				int val = dist[to];
				int nex = Current[val + 1];
				List[to].push_back(make_tuple(dist[pos], nex, pos));
			}
		}
	}
}

void dfs2(int pos, int col) {
	Group[pos] = col;
	used[pos] = true; tmp.push_back(pos);
	auto itr = H[pos].begin();
	while (itr != H[pos].end()) {
		int to = (*itr);
		if (used[to] == false) dfs2(to, col);
		itr++;
	}
}

void FindComponents(int pos, int col) {
	tmp.clear();
	dfs2(pos, col);
	for (int i : tmp) used[i] = false;
}

void DeleteEdge(int u, int v) {
	H[u].erase(v);
	H[v].erase(u);
}

void Delete(int pos) {
	map<int, int> Map;
	sort(List[pos].begin(), List[pos].end());
	
	// Deletion Start
	for (int i = 0; i < (int)List[pos].size(); i++) {
		int idx1 = get<1>(List[pos][i]);
		int idx2 = get<2>(List[pos][i]); if (Group[pos] != Group[idx2]) continue;
		
		// Edge Delete
		pair<int, int> u1 = make_pair(pos, idx1); if (Map[idx1] != 0) u1.second = Map[idx1] - 1;
		pair<int, int> u2 = make_pair(idx2, par[idx2]);
		DeleteEdge(u1.first, u1.second);
		DeleteEdge(u2.first, u2.second);
		H[pos].insert(idx2);
		H[idx2].insert(pos);
		
		// Division
		NumGroup += 1;
		FindComponents(par[idx2], NumGroup);
		Map[idx1] = idx2 + 1;
		par[idx2] = pos;
	}
}

int main() {
	// Input
	cin >> N >> M;
	for (int i = 0; i < M; i++) cin >> X[i] >> Y[i];
	for (int i = 1; i < M; i++) {
		int idx = rand() % (i + 1);
		swap(X[idx], X[i]);
		swap(Y[idx], Y[i]);
	}
	for (int i = 0; i < M; i++) {
		G[X[i]].push_back(Y[i]);
		G[Y[i]].push_back(X[i]);
	}
	
	// Calculate dp[i], par[i], List[i]
	int BOSS = rand() % N;
	for (int i = 0; i < N; i++) par[i] = -1;
	for (int i = 0; i < N; i++) dist[i] = -1;
	Current.push_back(BOSS);
	dfs1(BOSS, 0);
	
	// Split Edges
	for (int i = 0; i < N; i++) {
		if (dp[i] % 2 == 1 || i == BOSS) continue;
		DeleteEdge(i, par[i]);
		par[i] = -1;
	}
	
	// Get Connected Components
	for (int i = 0; i < N; i++) {
		if (Group[i] >= 1) continue;
		NumGroup += 1;
		FindComponents(i, NumGroup);
	}
	
	// Delete Edges
	vector<pair<int, int>> Order;
	for (int i = 0; i < N; i++) Order.push_back(make_pair(dist[i], i));
	sort(Order.begin(), Order.end());
	reverse(Order.begin(), Order.end());
	for (int i = 0; i < (int)Order.size(); i++) {
		Delete(Order[i].second);
	}
	
	// Finalize
	NumGroup = 0;
	for (int i = 0; i < N; i++) Group[i] = -1;
	for (int i = 0; i < N; i++) {
		if (Group[i] >= 1) continue;
		NumGroup += 1;
		FindComponents(i, NumGroup);
	}
	
	// Get Answer
	vector<vector<int>> Answer(NumGroup + 1, vector<int>(0, 0));
	for (int i = 0; i < N; i++) Answer[Group[i]].push_back(i);
	cout << NumGroup << endl;
	for (int i = 1; i <= NumGroup; i++) {
		cout << Answer[i].size();
		for (int j = 0; j < (int)Answer[i].size(); j++) cout << " " << Answer[i][j];
		cout << endl;
	}
	return 0;
}
accuracy: 0.4146341463414634
time_ms: 80
memory_kb: 32084
final_rank: 10

code_snippet: #include <iostream>
#include <vector>
#include <tuple>
#include <set>
#include <map>
#include <algorithm>
using namespace std;

// First Part
int N, M, X[100009], Y[100009];
int dist[100009], dp[100009], par[100009];
vector<int> G[100009];
vector<int> Current, tmp;

// Second Part
int NumGroup = 0;
int Group[100009];
bool used[100009];
vector<tuple<int, int, int>> List[100009]; // Non-Tree Edges
set<int> H[100009];

void Initialize() {
	NumGroup = 0;
	Current.clear(); tmp.clear();
	for (int i = 0; i < 109; i++) {
		dist[i] = 0; dp[i] = 0; par[i] = 0;
		G[i].clear();
		Group[i] = 0; used[i] = false; List[i].clear();
		H[i].clear();
	}
}

void dfs1(int pos, int dep) {
	dist[pos] = dep;
	dp[pos] = 1;
	for (int to : G[pos]) {
		if (dist[to] == -1) {
			Current.push_back(to); dfs1(to, dep + 1); Current.pop_back();
			par[to] = pos;
			dp[pos] += dp[to];
			H[pos].insert(to);
			H[to].insert(pos);
		}
		else {
			if (dist[pos] - dist[to] >= 2) {
				int val = dist[to];
				int nex = Current[val + 1];
				List[to].push_back(make_tuple(dist[pos], nex, pos));
			}
		}
	}
}

void dfs2(int pos, int col) {
	Group[pos] = col;
	used[pos] = true; tmp.push_back(pos);
	auto itr = H[pos].begin();
	while (itr != H[pos].end()) {
		int to = (*itr);
		if (used[to] == false) dfs2(to, col);
		itr++;
	}
}

void dfs3(int pos) {
	dp[pos] = 1;
	auto itr = H[pos].begin();
	while (itr != H[pos].end()) {
		int to = (*itr);
		if (dp[to] == -1) {
			dfs3(to);
			dp[pos] += dp[to];
		}
		itr++;
	}
}

void FindComponents(int pos, int col) {
	tmp.clear();
	dfs2(pos, col);
	for (int i : tmp) used[i] = false;
}

void DeleteEdge(int u, int v) {
	H[u].erase(v);
	H[v].erase(u);
}

void Delete(int pos) {
	map<int, int> Map;
	sort(List[pos].begin(), List[pos].end());
	
	// Deletion Start
	for (int i = 0; i < (int)List[pos].size(); i++) {
		int idx1 = get<1>(List[pos][i]);
		int idx2 = get<2>(List[pos][i]); if (Group[pos] != Group[idx2]) continue;
		
		// Edge Delete
		pair<int, int> u1 = make_pair(pos, idx1); if (Map[idx1] != 0) u1.second = Map[idx1] - 1;
		pair<int, int> u2 = make_pair(idx2, par[idx2]);
		DeleteEdge(u1.first, u1.second);
		DeleteEdge(u2.first, u2.second);
		H[pos].insert(idx2);
		H[idx2].insert(pos);
		
		// Division
		NumGroup += 1;
		FindComponents(par[idx2], NumGroup);
		Map[idx1] = idx2 + 1;
		par[idx2] = pos;
	}
}

bool solve(int boss) {
	// Calculate dp[i], par[i], List[i]
	for (int i = 0; i < N; i++) par[i] = -1;
	for (int i = 0; i < N; i++) dist[i] = -1;
	Current.push_back(boss);
	dfs1(boss, 0);
	
	// Split Edges
	for (int i = 0; i < N; i++) {
		if (dp[i] % 2 == 1 || i == boss) continue;
		DeleteEdge(i, par[i]);
		par[i] = -1;
	}
	
	// Get Connected Components
	for (int i = 0; i < N; i++) {
		if (Group[i] >= 1) continue;
		NumGroup += 1;
		FindComponents(i, NumGroup);
	}
	
	// Delete Edges
	vector<pair<int, int>> Order;
	for (int i = 0; i < N; i++) Order.push_back(make_pair(dist[i], i));
	sort(Order.begin(), Order.end());
	reverse(Order.begin(), Order.end());
	for (int i = 0; i < (int)Order.size(); i++) {
		Delete(Order[i].second);
	}
	
	// Finalize
	vector<bool> IsRoot(N, false);
	for (int i = 0; i < N; i++) dp[i] = -1;
	for (int i = 0; i < N; i++) {
		if (dp[i] != -1) continue;
		dfs3(i);
		IsRoot[i] = true;
	}
	for (int i = 0; i < N; i++) {
		if (IsRoot[i] == false && dp[i] % 2 == 0) return false;
	}
	
	// Get Answer
	vector<vector<int>> Answer(NumGroup + 1, vector<int>(0, 0));
	for (int i = 0; i < N; i++) Answer[Group[i]].push_back(i);
	cout << NumGroup << endl;
	for (int i = 1; i <= NumGroup; i++) {
		cout << Answer[i].size();
		for (int j = 0; j < (int)Answer[i].size(); j++) cout << " " << Answer[i][j];
		cout << endl;
	}
	return true;
}

int main() {
	// Input
	cin >> N >> M;
	for (int i = 0; i < M; i++) {
		cin >> X[i] >> Y[i];
	}
	
	// Get Answer
	while (true) {
		Initialize();
		vector<int> ord(M, 0);
		for (int i = 0; i < M; i++) ord[i] = i;
		for (int i = 0; i < M * 2; i++) {
			swap(ord[rand() % M], ord[rand() % M]);
		}
		for (int i = 0; i < M; i++) {
			G[X[ord[i]]].push_back(Y[ord[i]]);
			G[Y[ord[i]]].push_back(X[ord[i]]);
		}
		int boss = rand() % N;
		bool ret = solve(boss);
		if (ret == true) break;
	}
	return 0;
}
accuracy: 1
time_ms: 90
memory_kb: 33324
final_rank: 4

code_snippet: #include <iostream>
#include <vector>
#include <tuple>
#include <set>
#include <map>
#include <algorithm>
using namespace std;

// First Part
int N, M, X[100009], Y[100009];
int dist[100009], dp[100009], par[100009];
vector<int> G[100009];
vector<int> Current, tmp;

// Second Part
int NumGroup = 0;
int Group[100009];
bool used[100009];
vector<tuple<int, int, int>> List[100009]; // Non-Tree Edges
set<int> H[100009];

void dfs1(int pos, int dep) {
	dist[pos] = dep;
	dp[pos] = 1;
	for (int to : G[pos]) {
		if (dist[to] == -1) {
			Current.push_back(to); dfs1(to, dep + 1); Current.pop_back();
			par[to] = pos;
			dp[pos] += dp[to];
			H[pos].insert(to);
			H[to].insert(pos);
		}
		else {
			if (dist[pos] - dist[to] >= 2) {
				int val = dist[to];
				int nex = Current[val + 1];
				List[to].push_back(make_tuple(dist[pos], nex, pos));
			}
		}
	}
}

void dfs2(int pos, int col) {
	Group[pos] = col;
	used[pos] = true; tmp.push_back(pos);
	auto itr = H[pos].begin();
	while (itr != H[pos].end()) {
		int to = (*itr);
		if (used[to] == false) dfs2(to, col);
		itr++;
	}
}

void FindComponents(int pos, int col) {
	tmp.clear();
	dfs2(pos, col);
	for (int i : tmp) used[i] = false;
}

void DeleteEdge(int u, int v) {
	H[u].erase(v);
	H[v].erase(u);
}

void Delete(int pos) {
	map<int, int> Map;
	sort(List[pos].begin(), List[pos].end());
	
	// Deletion Start
	for (int i = 0; i < (int)List[pos].size(); i++) {
		int idx1 = get<1>(List[pos][i]);
		int idx2 = get<2>(List[pos][i]); if (Group[pos] != Group[idx2]) continue;
		
		// Edge Delete
		pair<int, int> u1 = make_pair(pos, idx1); if (Map[idx1] != 0) u1.second = Map[idx1] - 1;
		pair<int, int> u2 = make_pair(idx2, par[idx2]);
		DeleteEdge(u1.first, u1.second);
		DeleteEdge(u2.first, u2.second);
		H[pos].insert(idx2);
		H[idx2].insert(pos);
		
		// Division
		NumGroup += 1;
		FindComponents(par[idx2], NumGroup);
		Map[idx1] = idx2 + 1;
		par[idx2] = pos;
	}
}

int main() {
	// Input
	cin >> N >> M;
	for (int i = 0; i < M; i++) {
		cin >> X[i] >> Y[i];
		G[X[i]].push_back(Y[i]);
		G[Y[i]].push_back(X[i]);
	}
	
	// Calculate dp[i], par[i], List[i]
	for (int i = 0; i < N; i++) par[i] = -1;
	for (int i = 0; i < N; i++) dist[i] = -1;
	Current.push_back(0);
	dfs1(0, 0);
	
	// Split Edges
	for (int i = 0; i < N; i++) {
		if (dp[i] % 2 == 1 || i == 0) continue;
		DeleteEdge(i, par[i]);
		par[i] = -1;
	}
	
	// Get Connected Components
	for (int i = 0; i < N; i++) {
		if (Group[i] >= 1) continue;
		NumGroup += 1;
		FindComponents(i, NumGroup);
	}
	
	// Delete Edges
	vector<pair<int, int>> Order;
	for (int i = 0; i < N; i++) Order.push_back(make_pair(dist[i], i));
	sort(Order.begin(), Order.end());
	reverse(Order.begin(), Order.end());
	for (int i = 0; i < (int)Order.size(); i++) {
		Delete(Order[i].second);
	}
	
	// Finalize
	NumGroup = 0;
	for (int i = 0; i < N; i++) Group[i] = -1;
	for (int i = 0; i < N; i++) {
		if (Group[i] >= 1) continue;
		NumGroup += 1;
		FindComponents(i, NumGroup);
	}
	
	// Get Answer
	vector<vector<int>> Answer(NumGroup + 1, vector<int>(0, 0));
	for (int i = 0; i < N; i++) Answer[Group[i]].push_back(i);
	cout << NumGroup << endl;
	for (int i = 1; i <= NumGroup; i++) {
		cout << Answer[i].size();
		for (int j = 0; j < (int)Answer[i].size(); j++) cout << " " << Answer[i][j];
		cout << endl;
	}
	return 0;
}
accuracy: 0.2926829268292683
time_ms: 80
memory_kb: 33312
final_rank: 15

code_snippet: #include <iostream>
#include <vector>
#include <tuple>
#include <set>
#include <map>
#include <algorithm>
using namespace std;

// First Part
int N, M, X[100009], Y[100009];
int dist[100009], dp[100009], par[100009];
vector<int> G[100009];
vector<int> Current, tmp;

// Second Part
int NumGroup = 0;
int Group[100009];
bool used[100009];
vector<tuple<int, int, int>> List[100009]; // Non-Tree Edges
set<int> H[100009];

void dfs1(int pos, int dep) {
	dist[pos] = dep;
	dp[pos] = 1;
	for (int to : G[pos]) {
		if (dist[to] == -1) {
			Current.push_back(to); dfs1(to, dep + 1); Current.pop_back();
			par[to] = pos;
			dp[pos] += dp[to];
			H[pos].insert(to);
			H[to].insert(pos);
		}
		else {
			if (dist[pos] - dist[to] >= 2) {
				int val = dist[to];
				int nex = Current[val + 1];
				List[to].push_back(make_tuple(dist[pos], nex, pos));
			}
		}
	}
}

void dfs2(int pos, int col) {
	Group[pos] = col;
	used[pos] = true; tmp.push_back(pos);
	auto itr = H[pos].begin();
	while (itr != H[pos].end()) {
		int to = (*itr);
		if (used[to] == false) dfs2(to, col);
		itr++;
	}
}

void FindComponents(int pos, int col) {
	tmp.clear();
	dfs2(pos, col);
	for (int i : tmp) used[i] = false;
}

void DeleteEdge(int u, int v) {
	H[u].erase(v);
	H[v].erase(u);
}

void Delete(int pos) {
	map<int, int> Map;
	sort(List[pos].begin(), List[pos].end());
	
	// Deletion Start
	for (int i = 0; i < (int)List[pos].size(); i++) {
		int idx1 = get<1>(List[pos][i]);
		int idx2 = get<2>(List[pos][i]); if (Group[pos] != Group[idx2]) continue;
		
		// Edge Delete
		pair<int, int> u1 = make_pair(pos, idx1); if (Map[idx1] != 0) u1.second = Map[idx1] - 1;
		pair<int, int> u2 = make_pair(idx2, par[idx2]);
		DeleteEdge(u1.first, u1.second);
		DeleteEdge(u2.first, u2.second);
		H[pos].insert(idx2);
		H[idx2].insert(pos);
		
		// Division
		NumGroup += 1;
		FindComponents(par[idx2], NumGroup);
		Map[idx1] = idx2 + 1;
		par[idx2] = pos;
	}
}

int main() {
	// Input
	cin >> N >> M;
	for (int i = 0; i < M; i++) {
		cin >> X[i] >> Y[i];
		G[X[i]].push_back(Y[i]);
		G[Y[i]].push_back(X[i]);
	}
	
	// Calculate dp[i], par[i], List[i]
	for (int i = 0; i < N; i++) par[i] = -1;
	for (int i = 0; i < N; i++) dist[i] = -1;
	Current.push_back(0);
	dfs1(0, 0);
	
	// Split Edges
	for (int i = 0; i < N; i++) {
		if (dp[i] % 2 == 1 || i == 0) continue;
		DeleteEdge(i, par[i]);
		par[i] = -1;
	}
	
	// Get Connected Components
	for (int i = 0; i < N; i++) {
		if (Group[i] >= 1) continue;
		NumGroup += 1;
		FindComponents(i, NumGroup);
	}
	
	// Delete Edges
	vector<pair<int, int>> Order;
	for (int i = 0; i < N; i++) Order.push_back(make_pair(dist[i], i));
	sort(Order.begin(), Order.end());
	reverse(Order.begin(), Order.end());
	for (int i = 0; i < (int)Order.size(); i++) {
		Delete(Order[i].second);
	}
	
	// Get Answer
	vector<vector<int>> Answer(NumGroup + 1, vector<int>(0, 0));
	for (int i = 0; i < N; i++) Answer[Group[i]].push_back(i);
	cout << NumGroup << endl;
	for (int i = 1; i <= NumGroup; i++) {
		cout << Answer[i].size();
		for (int j = 0; j < (int)Answer[i].size(); j++) cout << " " << Answer[i][j];
		cout << endl;
	}
	return 0;
}
accuracy: 0.2926829268292683
time_ms: 80
memory_kb: 33160
final_rank: 14

code_snippet: #include <iostream>
#include <vector>
#include <tuple>
#include <set>
#include <map>
#include <algorithm>
using namespace std;

// First Part
int N, M, X[100009], Y[100009];
int dist[100009], dp[100009], par[100009];
vector<int> G[100009];
vector<int> Current, tmp;

// Second Part
int NumGroup = 0;
int Group[100009];
bool used[100009];
vector<tuple<int, int, int>> List[100009]; // Non-Tree Edges
set<int> H[100009];

void dfs1(int pos, int dep) {
	dist[pos] = dep;
	dp[pos] = 1;
	for (int to : G[pos]) {
		if (dist[to] == -1) {
			Current.push_back(to); dfs1(to, dep + 1); Current.pop_back();
			par[to] = pos;
			dp[pos] += dp[to];
			H[pos].insert(to);
			H[to].insert(pos);
		}
		else {
			if (dist[pos] - dist[to] >= 2) {
				int val = dist[to];
				int nex = Current[val + 1];
				List[to].push_back(make_tuple(dist[pos], nex, pos));
			}
		}
	}
}

void dfs2(int pos, int col) {
	Group[pos] = col;
	used[pos] = true; tmp.push_back(pos);
	auto itr = H[pos].begin();
	while (itr != H[pos].end()) {
		int to = (*itr);
		if (used[to] == false) dfs2(to, col);
		itr++;
	}
}

void FindComponents(int pos, int col) {
	tmp.clear();
	dfs2(pos, col);
	for (int i : tmp) used[i] = false;
}

void DeleteEdge(int u, int v) {
	H[u].erase(v);
	H[v].erase(u);
}

void Delete(int pos) {
	map<int, int> Map;
	sort(List[pos].begin(), List[pos].end());
	
	// Deletion Start
	for (int i = 0; i < (int)List[pos].size(); i++) {
		int idx1 = get<1>(List[pos][i]);
		int idx2 = get<2>(List[pos][i]); if (Group[pos] != Group[idx2]) continue;
		
		// Edge Delete
		pair<int, int> u1 = make_pair(pos, idx1); if (Map[idx1] != 0) u1.second = Map[idx1] - 1;
		pair<int, int> u2 = make_pair(idx2, par[idx2]);
		DeleteEdge(u1.first, u1.second);
		DeleteEdge(u2.first, u2.second);
		H[pos].insert(idx2);
		H[idx2].insert(pos);
		
		// Division
		NumGroup += 1;
		FindComponents(par[idx2], NumGroup);
		Map[idx1] = idx2;
		par[idx2] = pos;
	}
}

int main() {
	// Input
	cin >> N >> M;
	for (int i = 0; i < M; i++) {
		cin >> X[i] >> Y[i];
		G[X[i]].push_back(Y[i]);
		G[Y[i]].push_back(X[i]);
	}
	
	// Calculate dp[i], par[i], List[i]
	for (int i = 0; i < N; i++) par[i] = -1;
	for (int i = 0; i < N; i++) dist[i] = -1;
	Current.push_back(0);
	dfs1(0, 0);
	
	// Split Edges
	for (int i = 0; i < N; i++) {
		if (dp[i] % 2 == 1 || i == 0) continue;
		DeleteEdge(i, par[i]);
		par[i] = -1;
	}
	
	// Get Connected Components
	for (int i = 0; i < N; i++) {
		if (Group[i] >= 1) continue;
		NumGroup += 1;
		FindComponents(i, NumGroup);
	}
	
	// Delete Edges
	vector<pair<int, int>> Order;
	for (int i = 0; i < N; i++) Order.push_back(make_pair(dist[i], i));
	sort(Order.begin(), Order.end());
	reverse(Order.begin(), Order.end());
	for (int i = 0; i < (int)Order.size(); i++) {
		Delete(Order[i].second);
	}
	
	// Get Answer
	vector<vector<int>> Answer(NumGroup + 1, vector<int>(0, 0));
	for (int i = 0; i < N; i++) Answer[Group[i]].push_back(i);
	cout << NumGroup << endl;
	for (int i = 1; i <= NumGroup; i++) {
		cout << Answer[i].size();
		for (int j = 0; j < (int)Answer[i].size(); j++) cout << " " << Answer[i][j];
		cout << endl;
	}
	return 0;
}
accuracy: 0.2926829268292683
time_ms: 80
memory_kb: 33020
final_rank: 13

code_snippet: #include <iostream>
#include <utility>
#include <vector>

int main() {
    std::ios::sync_with_stdio(false);
    std::cin.tie(nullptr);

    int n, m;
    std::cin >> n >> m;

    std::vector<std::vector<int>> g(n);
    for (int i = 0; i < m; ++i) {
        int u, v;
        std::cin >> u >> v;
        g[u].push_back(v);
        g[v].push_back(u);
    }

    std::vector<int> dep(n);      // 深さ。後退辺の方向 (先祖方向 or 子孫方向) の判定に用いる
    std::vector<int> par(n, -1);  // 全域森の管理。{v, par[v]} が全域森の辺

    auto is_tree_edge = [&par](int u, int v) { return par[u] == v or par[v] == u; };

    std::vector<int8_t> visit(n);    // 既に訪問した頂点かどうか
    std::vector<int8_t> removed(n);  // 既に切り離された頂点かどうか

    std::vector<std::vector<int>> ans;
    auto collect = [&](int r) {  // 全域森で r が属する成分の頂点を集めて答えに追加
        auto &cmp = ans.emplace_back();
        auto collect_rec = [&](auto collect_rec, int cur, int prv) -> void {
            cmp.push_back(cur);
            removed[cur] = true;
            for (int nxt : g[cur]) if (is_tree_edge(cur, nxt) and nxt != prv) {
                collect_rec(collect_rec, nxt, cur);
            }
        };
        collect_rec(collect_rec, r, -1);
    };

    auto remove_even_subtrees = [&](auto remove_even_subtrees, int root) -> int {
        visit[root] = true;
        int sub_size = 1;
        for (int v : g[root]) if (not visit[v]) {
            par[v] = root;
            dep[v] = dep[root] + 1;
            sub_size += remove_even_subtrees(remove_even_subtrees, v);
        }

        if (sub_size % 2 == 0) {
            par[root] = -1; // 全域森から辺を削除 (root を根とする部分木を切り離す)
            auto remove_backward_edges = [&](auto remove_backward_edges, int u, int par_u) -> void {
                for (int v : g[u]) if (v != par_u) {
                    if (is_tree_edge(u, v)) {
                        remove_backward_edges(remove_backward_edges, v, u);
                    } else if (not removed[v] and dep[v] > dep[u]) { // 子孫方向の削除されていない後退辺
                        // 全域森から辺 {v, par[v]} を削除して辺 {v, u} を追加 / uとvの間にある頂点 r を列挙
                        for (int r = std::exchange(par[v], u); r != u;) {
                            // 辺 {r, par[r]} を削除
                            int nxt_r = std::exchange(par[r], -1);
                            collect(r);
                            r = nxt_r;
                        }
                    }
                }
            };
            remove_backward_edges(remove_backward_edges, root, -1);
            collect(root);
        }
        return sub_size;
    };
    remove_even_subtrees(remove_even_subtrees, 0);

    std::cout << ans.size() << '\n';
    for (const auto& cmp : ans) {
        std::cout << cmp.size();
        for (int v : cmp) std::cout << ' ' << v;
        std::cout << '\n';
    }
}
accuracy: 1
time_ms: 20
memory_kb: 37264
final_rank: 2

code_snippet: #include <iostream>
#include <utility>
#include <vector>

int main() {
    std::ios::sync_with_stdio(false);
    std::cin.tie(nullptr);

    int n, m;
    std::cin >> n >> m;

    std::vector<std::vector<int>> g(n);
    for (int i = 0; i < m; ++i) {
        int u, v;
        std::cin >> u >> v;
        g[u].push_back(v);
        g[v].push_back(u);
    }

    std::vector<std::vector<int>> ans;

    std::vector<int> dep(n);     // 後退辺の方向 (先祖方向 or 子孫方向) の判定用
    std::vector<int> par(n, -1); // 全域森の管理 ({ v, par[v] } が全域森の辺)

    auto is_tree_edge = [&](int u, int v) { return par[u] == v or par[v] == u; };

    std::vector<int8_t> visit(n, false); // 訪問済フラグ

    std::vector<int8_t> removed(n); // 既に切り離されてた頂点かどうかのフラグ

    // r が属する成分の頂点を集めて答えに追加する
    auto collect = [&](int r) {
        auto &cmp = ans.emplace_back();
        auto collect_rec = [&](auto collect_rec, int cur, int prv) -> void {
            cmp.push_back(cur);
            removed[cur] = true;
            for (int nxt : g[cur]) if (is_tree_edge(cur, nxt) and nxt != prv) {
                collect_rec(collect_rec, nxt, cur);
            }
        };
        collect_rec(collect_rec, r, -1);
    };

    auto remove_even_subtrees = [&](auto remove_even_subtrees, int root) -> int {
        visit[root] = true;
        int sub_size = 1;
        for (int v : g[root]) if (not visit[v]) {
            par[v] = root;
            dep[v] = dep[root] + 1;
            sub_size += remove_even_subtrees(remove_even_subtrees, v);
        }

        if (sub_size % 2 == 0) {
            par[root] = -1; // 全域森から辺を削除 (root を根とする部分木を切り離す)

            // 後退辺の除去
            auto remove_backward_edges = [&](auto remove_backward_edges, int u, int par_u) -> void {
                for (int v : g[u]) if (v != par_u) {
                    if (is_tree_edge(u, v)) {
                        remove_backward_edges(remove_backward_edges, v, u);
                    } else if (not removed[v] and dep[v] > dep[u]) { // 子孫方向の後退辺であるかどうか
                        // 辺 { v, par[v] } を全域森から削除して代わりに { v, u } を追加
                        int r = std::exchange(par[v], u);
                        // uv パス上の頂点 r を列挙 (u,vは含まない)
                        while (r != u) {
                            // 辺 { r, par[r] } を削除
                            int nxt_r = std::exchange(par[r], -1);
                            // (r を根とする部分木) - (prev_r を根とする部分木) に属する頂点を集める
                            collect(r);
                            r = nxt_r;
                        }
                    }
                }
            };
            remove_backward_edges(remove_backward_edges, root, -1);
            collect(root);
        }
        return sub_size;
    };
    remove_even_subtrees(remove_even_subtrees, 0);;

    std::cout << ans.size() << '\n';
    for (const auto& cmp : ans) {
        std::cout << cmp.size();
        for (int v : cmp) std::cout << ' ' << v;
        std::cout << '\n';
    }
}
accuracy: 1
time_ms: 30
memory_kb: 37228
final_rank: 3

code_snippet: #include <bits/stdc++.h>

using namespace std;

#define rep(i, n) for (int i = 0; i < (n); ++i)
#define rrep(i, n) for (int i = (n) - 1; i >= 0; --i)

#define all(c) std::begin(c), std::end(c)

#ifdef LOCAL
#define debug(...) debug_impl(#__VA_ARGS__, __VA_ARGS__)

template <class T, class ...Args> void debug_impl(string s, T&& f, Args &&...args) {
    cerr << '(' << s << "): (" << forward<T>(f);
    ((cerr << ", " << forward<Args>(args)), ..., (cerr << ')' << '\n'));
}
#else
#define debug(...) void(0)
#endif

template <typename T>
bool chmax(T& a, const T& b) { return b > a ? (a = b, true) : false; }
template <typename T>
bool chmin(T& a, const T& b) { return b < a ? (a = b, true) : false; }

template <typename T>
istream& operator>>(istream& in, vector<T>& v) {
    for (auto& e : v) in >> e;
    return in;
}
template <typename T>
ostream& operator<<(ostream& out, const vector<T>& v) {
    int n = v.size();
    rep(i, n) {
        out << v[i];
        if (i + 1 != n) out << ' ';
    }
    return out;
}

template <typename ...Args> void read(Args& ...args) {
    (cin >> ... >> args);
}
template <typename Head, typename ...Args> void print(Head&& h, Args&& ...tail) {
    cout << h, ((cout << ' ' << forward<Args>(tail)), ..., (cout << '\n'));
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    int n, m;
    read(n, m);

    vector<vector<int>> g(n);
    rep(i, m) {
        int u, v;
        read(u, v);
        g[u].push_back(v);
        g[v].push_back(u);
    }

    vector<int8_t> vis(n, false);
    vector<int> sub(n, 1);

    vector<vector<int>> ans;
    vector<int8_t> erased(n, false);

    vector<int> par(n);
    vector<int> dep(n);

    auto dfs = [&](auto dfs, int u, int p) -> void {
        par[u] = p;
        if (p >= 0) g[u].erase(find(all(g[u]), p));

        vis[u] = true;

        vector<int> rem;

        for (int v : g[u]) if (not erased[v]) {
            if (not vis[v]) {
                dep[v] = dep[u] + 1;
                dfs(dfs, v, u);
            } else if (dep[v] > dep[u]) {
                rem.push_back(v);
            }
        }

        for (int v : rem) if (not erased[v]) {
            int pw = v;
            for (int w = par[v]; w != u; w = par[w]) {
                auto &c = ans.emplace_back();
                auto collect = [&](auto collect, int u2, int p2) -> void {
                    c.push_back(u2);
                    for (int v2 : g[u2]) if ((par[u2] == v2 or par[v2] == u2) and v2 != p2 and v2 != pw and not erased[v2]) {
                        collect(collect, v2, u2);
                    }
                };
                collect(collect, w, par[w]);
                for (int x : c) erased[x] = true;
                pw = w;
            }
            par[v] = u;
        }

        if (sub[u] % 2 == 0) {
            auto& c = ans.emplace_back();
            auto collect = [&](auto collect, int u2, int p2) -> void {
                c.push_back(u2);
                for (int v2 : g[u2]) {
                    if ((par[v2] == u2 or par[u2] == v2) and v2 != p2 and not erased[v2]) {
                        collect(collect, v2, u2);
                    }
                }
            };
            collect(collect, u, p);
            for (int x : c) erased[x] = true;
        }
        if (p >= 0) {
            sub[p] += sub[u];
        }
    };
    dfs(dfs, 0, -1);

    print(ans.size());
    for (auto& c : ans) {
        print(c.size(), c);
    }
}
accuracy: 1
time_ms: 40
memory_kb: 58080
final_rank: 7

code_snippet: #include <bits/stdc++.h>

using namespace std;

#define rep(i, n) for (int i = 0; i < (n); ++i)
#define rrep(i, n) for (int i = (n) - 1; i >= 0; --i)

#define all(c) std::begin(c), std::end(c)

#ifdef LOCAL
#define debug(...) debug_impl(#__VA_ARGS__, __VA_ARGS__)

template <class T, class ...Args> void debug_impl(string s, T&& f, Args &&...args) {
    cerr << '(' << s << "): (" << forward<T>(f);
    ((cerr << ", " << forward<Args>(args)), ..., (cerr << ')' << '\n'));
}
#else
#define debug(...) void(0)
#endif

template <typename T>
bool chmax(T& a, const T& b) { return b > a ? (a = b, true) : false; }
template <typename T>
bool chmin(T& a, const T& b) { return b < a ? (a = b, true) : false; }

template <typename T>
istream& operator>>(istream& in, vector<T>& v) {
    for (auto& e : v) in >> e;
    return in;
}
template <typename T>
ostream& operator<<(ostream& out, const vector<T>& v) {
    int n = v.size();
    rep(i, n) {
        out << v[i];
        if (i + 1 != n) out << ' ';
    }
    return out;
}

template <typename ...Args> void read(Args& ...args) {
    (cin >> ... >> args);
}
template <typename Head, typename ...Args> void print(Head&& h, Args&& ...tail) {
    cout << h, ((cout << ' ' << forward<Args>(tail)), ..., (cout << '\n'));
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    int n, m;
    read(n, m);

    vector<vector<int>> g(n);
    rep(i, m) {
        int u, v;
        read(u, v);
        g[u].push_back(v);
        g[v].push_back(u);
    }

    vector<int8_t> vis(n, false);
    vector<int> sub(n, 1);

    vector<vector<int>> ans;
    vector<int8_t> erased(n, false);

    vector<int> par(n);
    vector<int> dep(n);

    auto dfs = [&](auto dfs, int u, int p) -> void {
        par[u] = p;
        if (p >= 0) g[u].erase(find(all(g[u]), p));

        vis[u] = true;

        vector<int> rem;

        for (int v : g[u]) if (not erased[v]) {
            if (not vis[v]) {
                dep[v] = dep[u] + 1;
                dfs(dfs, v, u);

                if (sub[v] % 2 == 0) {
                    assert(not erased[v]);
                    auto& c = ans.emplace_back();
                    auto collect = [&](auto collect, int u2, int p2) -> void {
                        c.push_back(u2);
                        for (int v2 : g[u2]) if (v2 != p2) {
                            if ((par[v2] == u2 or par[u2] == v2) and not erased[v2]) {
                                collect(collect, v2, u2);
                            }
                        }
                    };
                    collect(collect, v, u);
                    for (int x : c) {
                        erased[x] = true;
                    }
                }
                sub[u] += sub[v];
            } else if (vis[v] and dep[v] > dep[u] and sub[v] % 2 == 1) {
                rem.push_back(v);
            }
        }

        g[u].erase(remove_if(all(g[u]), [&](int v) { return erased[v]; }), g[u].end());

        for (int v : rem) if (not erased[v]) {
            int pw = v;
            for (int w = par[v]; w != u; w = par[w]) {
                auto &c = ans.emplace_back();
                auto collect = [&](auto collect, int u2, int p2) -> void {
                    c.push_back(u2);
                    for (int v2 : g[u2]) if ((par[u2] == v2 or par[v2] == u2) and p2 != v2 and not erased[v2]) {
                        if (v2 == pw or v2 == par[w]) continue;
                        collect(collect, v2, u2);
                    }
                };
                collect(collect, w, -1);
                for (int x : c) {
                    erased[x] = true;
                }
                pw = w;
            }
            par[v] = u;
        }

        g[u].erase(remove_if(all(g[u]), [&](int v) { return erased[v]; }), g[u].end());
    };
    dfs(dfs, 0, -1);

    {
        auto& c = ans.emplace_back();
        rep(i, n) if (not erased[i]) c.push_back(i);
        if (c.empty()) ans.pop_back();
    }

    print(ans.size());
    for (auto& c : ans) {
        print(c.size(), c);
    }
}
accuracy: 1
time_ms: 30
memory_kb: 54028
final_rank: 6

code_snippet: #include <bits/stdc++.h>

using namespace std;

#define rep(i, n) for (int i = 0; i < (n); ++i)
#define rrep(i, n) for (int i = (n) - 1; i >= 0; --i)

#define all(c) std::begin(c), std::end(c)

#ifdef LOCAL
#define debug(...) debug_impl(#__VA_ARGS__, __VA_ARGS__)

template <class T, class ...Args> void debug_impl(string s, T&& f, Args &&...args) {
    cerr << '(' << s << "): (" << forward<T>(f);
    ((cerr << ", " << forward<Args>(args)), ..., (cerr << ')' << '\n'));
}
#else
#define debug(...) void(0)
#endif

template <typename T>
bool chmax(T& a, const T& b) { return b > a ? (a = b, true) : false; }
template <typename T>
bool chmin(T& a, const T& b) { return b < a ? (a = b, true) : false; }

template <typename T>
istream& operator>>(istream& in, vector<T>& v) {
    for (auto& e : v) in >> e;
    return in;
}
template <typename T>
ostream& operator<<(ostream& out, const vector<T>& v) {
    int n = v.size();
    rep(i, n) {
        out << v[i];
        if (i + 1 != n) out << ' ';
    }
    return out;
}

template <typename ...Args> void read(Args& ...args) {
    (cin >> ... >> args);
}
template <typename Head, typename ...Args> void print(Head&& h, Args&& ...tail) {
    cout << h, ((cout << ' ' << forward<Args>(tail)), ..., (cout << '\n'));
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    int n, m;
    read(n, m);

    vector<vector<int>> g(n), t(n);
    rep(i, m) {
        int u, v;
        read(u, v);
        g[u].push_back(v);
        g[v].push_back(u);
    }

    vector<int8_t> vis(n, false);
    vector<int> sub(n, 1);

    vector<vector<int>> ans;
    vector<int8_t> erased(n, false);

    vector<int> par(n);
    vector<int> dep(n);

    auto dfs = [&](auto dfs, int u, int p) -> void {
        par[u] = p;
        if (p >= 0) {
            g[u].erase(find(all(g[u]), p));
        }
        vis[u] = true;

        vector<int> rem;

        for (int v : g[u]) if (not erased[v]) {
            if (not vis[v]) {
                t[u].push_back(v);
                t[v].push_back(u);

                dep[v] = dep[u] + 1;
                dfs(dfs, v, u);

                if (sub[v] % 2 == 0) {
                    assert(not erased[v]);
                    auto& c = ans.emplace_back();
                    auto collect = [&](auto collect, int u2, int p2) -> void {
                        assert(par[u2] == p2);
                        c.push_back(u2);
                        for (int v2 : t[u2]) if (v2 != p2 and not erased[v2]) {
                            collect(collect, v2, u2);
                        }
                    };
                    collect(collect, v, u);
                    assert(int(c.size()) == 2);
                    for (int x : c) {
                        erased[x] = true;
                    }
                }
                sub[u] += sub[v];
            } else if (vis[v] and dep[v] > dep[u] and sub[v] % 2 == 1) {
                rem.push_back(v);
            }
        }

        g[u].erase(remove_if(all(g[u]), [&](int v) { return erased[v]; }), g[u].end());

        for (int v : rem) if (not erased[v]) {
            auto& c = ans.emplace_back();
            auto collect = [&](auto collect, int u2, int p2) -> void {
                if (p2 >= 0) {
                    assert(par[u2] == p2 or par[p2] == u2);
                }
                c.push_back(u2);
                for (int v2 : t[u2]) if (v2 != p2 and not erased[v2]) {
                    if (v2 == v or v2 == u) continue;
                    collect(collect, v2, u2);
                }
            };
            assert(par[v] >= 0);
            collect(collect, par[v], -1);
            for (int x : c) {
                erased[x] = true;
            }
            if (c.empty()) ans.pop_back();
            par[v] = u;
            t[v].push_back(u);
            t[u].push_back(v);
        }

        g[u].erase(remove_if(all(g[u]), [&](int v) { return erased[v]; }), g[u].end());
    };
    dfs(dfs, 0, -1);

    {
        auto &c = ans.emplace_back();
        rep(i, n) if (not erased[i]) c.push_back(i);
        if (c.empty()) ans.pop_back();
    }

    print(ans.size());
    for (auto &c : ans) {
        assert(c.size() % 2 == 0);
        print(c.size(), c);
    }
}
accuracy: 0.04878048780487805
time_ms: 30
memory_kb: 53348
final_rank: 20