#include <bits/stdc++.h>
using namespace std;
template <class T>
inline T abs(T &a) {
  return a > 0 ? a : -a;
}
template <class T>
inline T min(T &a, T &b) {
  return a < b ? a : b;
}
template <class T>
inline T max(T &a, T &b) {
  return a > b ? a : b;
}
inline void read(int &x) {
  char ch;
  while ((ch = getchar()) && !(ch >= '0' && ch <= '9'))
    ;
  x = ch - '0';
  while ((ch = getchar()) && (ch >= '0' && ch <= '9')) x = x * 10 + ch - '0';
}
struct point {
  int x, y;
  point() {}
  point(int _x, int _y) : x(_x), y(_y) {}
};
const int N = 120000;
stack<int> Q[N];
vector<int> E[N], F[N];
int dep[N], dm, is[N], n, m, vis[N];
void dfs(int w, int Fa) {
  dep[w] = dep[Fa] + 1;
  dm = max(dm, dep[w]);
  F[dep[w]].push_back(w);
  vis[w] = is[w] = 1;
  for (int i = 0; i < E[w].size(); i++) {
    if (vis[E[w][i]]) Q[w].push(E[w][i]);
    if (!is[E[w][i]] && E[w][i] != Fa) dfs(E[w][i], w);
  }
  vis[w] = 0;
}
int main() {
  scanf("%d%d", &n, &m);
  int x, y;
  if (m & 1) {
    puts("No solution");
    return 0;
  }
  for (int i = 1; i <= m; i++) {
    scanf("%d%d", &x, &y);
    E[x].push_back(y);
    E[y].push_back(x);
  }
  dfs(1, 0);
  for (int d = dm; d >= 1; d--) {
    for (int i = 0; i < F[d].size(); i++) {
      int x = F[d][i];
      while (Q[x].size() >= 2) {
        int p = Q[x].top();
        Q[x].pop();
        int q = Q[x].top();
        Q[x].pop();
        printf("%d %d %d\n", p, x, q);
      }
      if (Q[x].size()) Q[Q[x].top()].push(x), Q[x].pop();
    }
  }
}
