#include <bits/stdc++.h>
using namespace std;
struct edge {
  int a, b, flag;
};
int dfs(int u, vector<int>* G, vector<edge>& A) {
  vector<int> now;
  for (int i = 0; i < (int(G[u].size())); i++)
    if (!A[G[u][i]].flag) now.push_back(G[u][i]);
  vector<int> topair;
  for (int i = 0; i < (int(now.size())); i++) A[now[i]].flag = 1;
  for (int i = 0; i < (int(now.size())); i++) {
    int to = (A[now[i]].a == u ? A[now[i]].b : A[now[i]].a);
    int x = dfs(to, G, A);
    if (x == -1)
      topair.push_back(to);
    else
      cout << x + 1 << ' ' << to + 1 << ' ' << u + 1 << '\n';
  }
  for (int i = 0; i < (int(topair.size())) - 1; i += 2)
    cout << topair[i] + 1 << ' ' << u + 1 << ' ' << topair[i + 1] + 1 << '\n';
  if ((int(topair.size())) % 2 == 0)
    return -1;
  else
    return topair.back();
}
int main() {
  ios::sync_with_stdio(0);
  int n, m;
  cin >> n >> m;
  vector<int>* G = new vector<int>[n];
  vector<edge> A(m);
  if (m % 2 == 1) {
    cout << "No solution\n";
    return 0;
  }
  for (int i = 0; i < m; i++) {
    cin >> A[i].a >> A[i].b;
    A[i].a--, A[i].b--;
    A[i].flag = 0;
    G[A[i].a].push_back(i);
    G[A[i].b].push_back(i);
  }
  dfs(0, G, A);
  return 0;
}
