1+ #pragma GCC optimize("Ofast")
2+ #pragma GCC optimize("unroll-loops")
3+ #include < bits/stdc++.h>
4+ using namespace std ;
5+
6+ typedef long long ll;
7+ typedef vector<int > vi;
8+ #define fast_cin () \
9+ ios_base::sync_with_stdio (false ); \
10+ cin.tie(NULL ); \
11+ cout.tie(NULL );
12+
13+ int n, e;
14+ vector<unordered_set<int >> adjlist;
15+ int main () {
16+ int tc;
17+ cin >> tc;
18+ while (tc--) {
19+ cin >> n >> e;
20+ adjlist.assign (n, unordered_set<int >());
21+
22+ vector<tuple<int , int , int >> ans;
23+ for (int i = 0 ; i < e; i++) {
24+ int u, v;
25+ cin >> u >> v;
26+ u--;
27+ v--;
28+ adjlist[u].insert (v);
29+ adjlist[v].insert (u);
30+ }
31+
32+ queue<int > q; // nodes that have > degree 1
33+ for (int i = 0 ; i < n; i++) {
34+ if (adjlist[i].size () > 1 ) {
35+ q.push (i);
36+ }
37+ }
38+
39+ while (!q.empty ()) {
40+ int u = q.front ();
41+ q.pop ();
42+ while (adjlist[u].size () > 1 ) {
43+ int v1 = *adjlist[u].begin ();
44+ int v2 = *(++adjlist[u].begin ());
45+ assert (v1 != v2);
46+
47+ ans.emplace_back (u, v1, v2);
48+ adjlist[v2].erase (u);
49+ adjlist[v1].erase (u);
50+ adjlist[u].erase (v1);
51+ adjlist[u].erase (v2);
52+ if (adjlist[v1].find (v2) == adjlist[v1].end ()) {
53+ // delete each other too
54+ adjlist[v1].insert (v2);
55+ adjlist[v2].insert (v1);
56+ } else {
57+ adjlist[v1].erase (v2);
58+ adjlist[v2].erase (v1);
59+ }
60+ }
61+ }
62+
63+ vector<pair<int , int >> pairs;
64+ vector<int > singles;
65+
66+ for (int i = 0 ; i < n; i++) {
67+ if (adjlist[i].size () == 0 ) {
68+ singles.push_back (i);
69+ } else if (adjlist[i].size () == 1 ) {
70+ if (i < *adjlist[i].begin ()) pairs.emplace_back (i, *adjlist[i].begin ());
71+ } else {
72+ assert (false );
73+ }
74+ }
75+
76+ if (pairs.size () == 0 ) { // empty
77+ assert (ans.size () <= 2 * max (n, e));
78+
79+ cout << ans.size () << endl;
80+ for (auto [u, v1, v2] : ans) {
81+ cout << u + 1 << " " << v1 + 1 << " " << v2 + 1 << endl;
82+ }
83+ continue ;
84+ }
85+
86+ // make a tree
87+ int root = pairs[0 ].first ;
88+ for (int i = 1 ; i < pairs.size (); i++) {
89+ ans.emplace_back (root, pairs[i].first , pairs[i].second );
90+ }
91+
92+ int curl = pairs[0 ].first ;
93+ int curr = pairs[0 ].second ;
94+
95+ for (auto s : singles) {
96+ ans.emplace_back (curl, curr, s);
97+ curr = curl;
98+ curl = s;
99+ }
100+
101+ cout << ans.size () << endl;
102+ assert (ans.size () <= 2 * max (n, e));
103+ for (auto [u, v1, v2] : ans) {
104+ cout << u + 1 << " " << v1 + 1 << " " << v2 + 1 << endl;
105+ }
106+ }
107+
108+ return 0 ;
109+ }
0 commit comments