#include <bits/stdc++.h>
#pragma GCC optimize("Ofast")
#pragma GCC target( \
    "avx,avx2,fma,sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
using namespace std;
long long MOD = 1e9 + 7;
const int N = 200000;
vector<pair<long long, pair<long long, long long> > > ans;
vector<pair<long long, long long> > gr[N];
pair<long long, long long> used[N];
long long used2[N];
pair<long long, long long> dfs(long long v) {
  if (used[v].first > -2) {
    return used[v];
  }
  vector<pair<long long, long long> > bd;
  for (auto ii : gr[v]) {
    long long i = ii.first;
    long long i2 = ii.second;
    if (!used2[i2]) {
      used2[i2] = 1;
      auto a = dfs(i);
      if (a.first == -1) {
        bd.push_back(ii);
      } else {
        ans.push_back({v, {i, a.first}});
        used2[i2] = 1;
        used2[a.second] = 1;
      }
    }
  }
  for (int i = 1; i < bd.size(); i += 2) {
    ans.push_back({bd[i - 1].first, {v, bd[i].first}});
    used2[bd[i - 1].second] = 1;
    used2[bd[i].second] = 1;
  }
  if (bd.size() % 2 == 0) {
    used[v] = {-1, -1};
    return used[v];
  } else {
    used[v] = bd[bd.size() - 1];
    return bd[bd.size() - 1];
  }
}
int main() {
  ios::sync_with_stdio(0), cin.tie(0), cout.tie(0),
      cout << fixed << setprecision(20);
  for (int i = 0; i < N; i++) {
    used[i].first = -2;
  }
  long long n, m;
  cin >> n >> m;
  if (m % 2 != 0) {
    cout << "No solution";
    return 0;
  }
  for (int i = 0; i < m; i++) {
    long long u, v;
    cin >> u >> v;
    u--, v--;
    gr[u].push_back({v, i});
    gr[v].push_back({u, i});
  }
  dfs(0);
  for (auto i : ans) {
    cout << i.first + 1 << " " << i.second.first + 1 << " "
         << i.second.second + 1 << endl;
  }
}
