//highlight: bacalo mi je TLE kad sam ispisivao zvjezdice, razmake i stringove jedan po jedan, kad sam ih spremao u StringBuilder pa na kraju cijelog ispisao bilo je puuuno ispod time limita
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;

public class CenterAlignment_5B {
	public static void main(String[] args) throws IOException {
		Scanner s = new Scanner(System.in);
		List<String> strings = new ArrayList<>();
		int maxLen = 0;
		StringBuilder out = new StringBuilder();
		String next = s.nextLine();
		while (s.hasNext()) {
			if (next.length() > maxLen) {
				maxLen = next.length();
			}
			strings.add(next);
			next = s.nextLine();
		}
		int diff;
		int halfDiff;
		int x = 0;
		int i;
		for (i = 1; i <= maxLen + 2; i++) {
			out.append("*");
		}
		out.append("\n");
		for (String line : strings) {
			out.append("*");
			diff = maxLen - line.length();
			halfDiff = diff / 2;
			if (diff % 2 == 0) {
				for (i = 1; i <= halfDiff; i++) {
					out.append(" ");
				}
				out.append(line);
				for (i = 1; i <= halfDiff; i++) {
					out.append(" ");
				}
			} else {// diff odd
				if (x % 2 == 0) {
					for (i = 1; i <= halfDiff; i++) {
						out.append(" ");
					}
					out.append(line);
					for (i = 1; i <= halfDiff + 1; i++) {
						out.append(" ");
					}
				} else {
					for (i = 1; i <= halfDiff + 1; i++) {
						out.append(" ");
					}
					out.append(line);
					for (i = 1; i <= halfDiff; i++) {
						out.append(" ");
					}
				}
				x++;
			}
			out.append("*");
			out.append("\n");
		}
		for (i = 1; i <= maxLen + 2; i++) {
			out.append("*");
		}
		System.out.println(out);
	}
}


import java.util.LinkedList;
import java.util.List;
import java.util.Scanner;

public class CenterAlignment_5B {
	public static void main(String[] args) {
		Scanner s = new Scanner(System.in);
		List<String> strings = new LinkedList<>();
		int maxLen = 0;
		String next;
		while (s.hasNextLine()) {
			next = s.nextLine();
			if (next.length() > maxLen) {
				maxLen = next.length();
			}
			strings.add(next);
		}
		int diff;
		int x = 0;
		for (int i = 1; i <= maxLen + 2; i++) {
			System.out.print("*");
		}
		System.out.println();
		for (String line : strings) {
			System.out.print("*");
			diff = maxLen - line.length();
			if (diff % 2 == 0) {
				for (int j = 1; j <= diff / 2; j++) {
					System.out.print(" ");
				}
				System.out.print(line);
				for (int j = 1; j <= diff / 2; j++) {
					System.out.print(" ");
				}
			} else {// diff odd
				if (x % 2 == 0) {
					for (int j = 1; j <= (diff / 2); j++) {
						System.out.print(" ");
					}
					System.out.print(line);
					for (int j = 1; j <= (diff / 2) + 1; j++) {
						System.out.print(" ");
					}
				} else {
					for (int j = 1; j <= (diff / 2) + 1; j++) {
						System.out.print(" ");
					}
					System.out.print(line);
					for (int j = 1; j <= (diff / 2); j++) {
						System.out.print(" ");
					}
				}
			}
			System.out.print("*");
			System.out.println();
		}
		for (int i = 1; i <= maxLen + 2; i++) {
			System.out.print("*");
		}
	}
}


import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Scanner;

public class CenterAlginment {

	public static void main(String[] args) throws IOException {
		// TODO Auto-generated method stub

		//Scanner input = new Scanner(System.in);
		String[] s= new String[1000];
		int i=0;
		int ma = 0;
		BufferedReader b = new BufferedReader(new InputStreamReader(System.in));
		String input = b.readLine();
		while(input!=null){
			s[i] = input;

		  ma = (int)Math.max(ma,s[i].length());
		  i++;
		  input  = b.readLine();
		}

		for( int j=0; j<ma+2; j++)System.out.print("*");
		System.out.println();
		for(int j=0;j<i;j++){
			System.out.print("*");
			int len = ma - s[i].length();
			for(int tmp=0;tmp<len/2;tmp++)System.out.print(" ");
			System.out.print(s[i]);
			for(int tmp=0;tmp<(int)Math.ceil(len/2);tmp++)System.out.print(" ");
			System.out.println("*");
		}
		for( int j=0; j<ma+2; j++)System.out.print("*");
	}

}


import java.io.*;
import java.util.*;

public class Main {
	public static void main(String[] args) throws IOException{
		BufferedReader b = new BufferedReader(new InputStreamReader(System.in));
		StringBuilder s = new StringBuilder();
		ArrayList<String> lines = new ArrayList<String>();

		String input = b.readLine();
		int max = input.length();
		boolean left = true;

		while(input != null){
			lines.add(input);
			if(input.length() > max){
				max = input.length();
			}
			input = b.readLine();
		}
		for(int i=0; i<max+2; i++){
			s.append('*');
		}
		s.append('\n');

		for (String line : lines) {
			double l = (max - line.length()) / 2.0;
			double r = (max - line.length()) / 2.0;
			if(left){
				r += 0.5;
			} else {
				l += 0.5;
			}
			if((int)l != (int)r){
				left = !left;
			}
			s.append('*');
			for(int i=0; i<(int)l; i++){
				s.append(' ');
			}
			s.append(line);
			for(int i=0; i<(int)r; i++){
				s.append(' ');
			}
			s.append("*\n");
		}
		for(int i=0; i<max+2; i++){
			s.append('*');
		}
		System.out.println(s);
	}
}


import java.io.*;
import java.util.*;

public class Main {
	public static void main(String[] args) throws IOException{
		BufferedReader b = new BufferedReader(new InputStreamReader(System.in));

		ArrayList<String> lines = new ArrayList<String>();

		String input = b.readLine();
		int max = input.length();
		boolean left = true;

		while(input != null){
			lines.add(input);
			if(input.length() > max){
				max = input.length();
			}
			input = b.readLine();
		}
		for(int i=0; i<max+2; i++){
			System.out.print('*');
		}
		System.out.println();

		for (String line : lines) {
			double l = (max - line.length()) / 2.0;
			double r = (max - line.length()) / 2.0;
			if(left){
				l += 0.5;
			} else {
				r += 0.5;
			}
			System.out.print('*');
			for(int i=0; i<(int)l; i++){
				System.out.print(' ');
			}
			System.out.print(line);
			for(int i=0; i<(int)r; i++){
				System.out.print(' ');
			}
			System.out.println('*');
		}
		for(int i=0; i<max+2; i++){
			System.out.print('*');
		}
		System.out.println();
	}
}


import java.io.*;
import java.util.*;

public class Main {
	public static void main(String[] args) throws IOException{
		BufferedReader b = new BufferedReader(new InputStreamReader(System.in));

		ArrayList<String> lines = new ArrayList<String>();

		String input = b.readLine();
		int max = input.length();
		boolean left = true;

		while(input != null){
			lines.add(input);
			if(input.length() > max){
				max = input.length();
			}
			input = b.readLine();
		}
		for(int i=0; i<max+2; i++){
			System.out.print('*');
		}
		System.out.println();

		for (String line : lines) {
			double l = (max - line.length()) / 2.0;
			double r = (max - line.length()) / 2.0;
			if(left){
				r += 0.5;
			} else {
				l += 0.5;
			}
			if((int)l != (int)r){
				left = !left;
			}
			System.out.print('*');
			for(int i=0; i<(int)l; i++){
				System.out.print(' ');
			}
			System.out.print(line);
			for(int i=0; i<(int)r; i++){
				System.out.print(' ');
			}
			System.out.println('*');
		}
		for(int i=0; i<max+2; i++){
			System.out.print('*');
		}
		System.out.println();
	}
}


import java.io.*;
import java.util.*;

public class Main {
	public static void main(String[] args) throws IOException{
		BufferedReader b = new BufferedReader(new InputStreamReader(System.in));

		ArrayList<String> lines = new ArrayList<String>();

		String input = b.readLine();
		int max = input.length();
		boolean left = true;

		while(input != null){
			lines.add(input);
			if(input.length() > max){
				max = input.length();
			}
			input = b.readLine();
		}
		for(int i=0; i<max+2; i++){
			System.out.print('*');
		}
		System.out.println();

		for (String line : lines) {
			double l = (max - line.length()) / 2.0;
			double r = (max - line.length()) / 2.0;
			if(left){
				r += 0.5;
			} else {
				l += 0.5;
			}
			if((max - line.length()) % 2 == 0){
				left = !left;
			}
			System.out.print('*');
			for(int i=0; i<(int)l; i++){
				System.out.print(' ');
			}
			System.out.print(line);
			for(int i=0; i<(int)r; i++){
				System.out.print(' ');
			}
			System.out.println('*');
		}
		for(int i=0; i<max+2; i++){
			System.out.print('*');
		}
		System.out.println();
	}
}


import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.util.Locale;
import java.util.StringTokenizer;

public class B_5 {
	static StringTokenizer st;
	static BufferedReader br;
	static PrintWriter pw;

	public static void main(String[] args) throws IOException {
		Locale.setDefault(Locale.US);
		br = new BufferedReader(new FileReader(new File("input.txt")));
		pw = new PrintWriter(new BufferedWriter(new OutputStreamWriter(
				System.out)));

		int n = 0;
		int ml = 0;
		String[] a = new String[100000];
		while (br.ready()) {
			a[++n] = br.readLine();
			ml = Math.max(ml, a[n].length());
		}
		for (int i = 0; i <= ml + 1; i++) {
			System.out.print('*');
		}
		System.out.println();
		int l = 0;
		for (int i = 1; i <= n; i++) {
			int pr = (ml - a[i].length()) / 2;
			String p = "";
			for (int j = 0; j < pr; j++) {
				p += " ";
			}
			if ((ml - a[i].length()) % 2 == 0) {
				a[i] = p + a[i] + p;
			} else {
				if (l % 2 == 0) {
					a[i] = p + a[i] + p + " ";
				} else {
					a[i] = " " + p + a[i] + p;
				}
				l++;
			}
			a[i] = "*" + a[i] + "*";
			pw.println(a[i]);
		}
		for (int i = 0; i <= ml + 1; i++)
			pw.print('*');
		pw.close();
	}

	private static int nextInt() throws IOException {
		return Integer.parseInt(next());
	}

	private static long nextLong() throws IOException {
		return Long.parseLong(next());
	}

	private static double nextDouble() throws IOException {
		return Double.parseDouble(next());
	}

	private static String next() throws IOException {
		while (st == null || !st.hasMoreTokens())
			st = new StringTokenizer(br.readLine());
		return st.nextToken();
	}
}


import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.util.Locale;
import java.util.StringTokenizer;

public class B_5 {
	static StringTokenizer st;
	static BufferedReader br;
	static PrintWriter pw;

	public static void main(String[] args) throws IOException {
		Locale.setDefault(Locale.US);
		br = new BufferedReader(new InputStreamReader(System.in));
		pw = new PrintWriter(new BufferedWriter(new OutputStreamWriter(
				System.out)));

		int n = 0;
		int ml = 0;
		String[] a = new String[100000];
		while (br.ready()) {
			a[++n] = br.readLine();
			ml = Math.max(ml, a[n].length());
		}
		for (int i = 0; i <= ml + 1; i++) {
			System.out.print('*');
		}
		System.out.println();
		int l = 0;
		for (int i = 1; i <= n; i++) {
			int pr = (ml - a[i].length()) / 2;
			String p = "";
			for (int j = 0; j < pr; j++) {
				p += " ";
			}
			if ((ml - a[i].length()) % 2 == 0) {
				a[i] = p + a[i] + p;
			} else {
				if (l % 2 == 0) {
					a[i] = p + a[i] + p + " ";
				} else {
					a[i] = " " + p + a[i] + p;
				}
				l++;
			}
			a[i] = "*" + a[i] + "*";
			pw.println(a[i]);
		}
		for (int i = 0; i <= ml + 1; i++)
			pw.print('*');
		pw.close();
	}

	private static int nextInt() throws IOException {
		return Integer.parseInt(next());
	}

	private static long nextLong() throws IOException {
		return Long.parseLong(next());
	}

	private static double nextDouble() throws IOException {
		return Double.parseDouble(next());
	}

	private static String next() throws IOException {
		while (st == null || !st.hasMoreTokens())
			st = new StringTokenizer(br.readLine());
		return st.nextToken();
	}
}


import java.util.*;

public class CenterAllignment {

    public static void main(String[] args) throws java.lang.Exception {

        Scanner input = new Scanner(System.in);
        ArrayList<String> lines = new ArrayList<String>();
        int maxLine = 0;
        String line = new String();

        while (input.hasNextLine())
        {
            line = input.nextLine();
            maxLine = Math.max(maxLine, line.length());
            lines.add(line);
        }

        for (int i=0 ; i<maxLine+2 ; ++i)
            System.out.print("*");
        System.out.println();

        boolean align = true;
        for (String l : lines) {
            int diff = maxLine-l.length();
            int startPos = diff/2;

            if(diff%2==1){
                if(!align)
                    startPos++;
                align = !align;
            }

            System.out.print("*");

            for (int j=0 ; j<startPos ; j++)
                System.out.print(" ");
            System.out.print(l);
            for (int j=startPos+l.length() ; j<maxLine ; j++)
                System.out.print(" ");

            System.out.println("*");
        }

        for (int i=0 ; i<maxLine+2 ; ++i)
            System.out.print("*");
        System.out.println();
        input.close();
    }
}


import java.util.*;

public class CenterAllignment {

    public static void main(String[] args) throws java.lang.Exception {

        Scanner input = new Scanner(System.in);
        ArrayList<String> lines = new ArrayList<String>();
        int maxLine = 0;
        String line = new String();

        while (input.hasNextLine())
        {
            line = input.nextLine();
            maxLine = Math.max(maxLine, line.length());
            lines.add(line);
        }

        for (int i=0 ; i<maxLine+2 ; ++i)
            System.out.print("*");
        System.out.println();

        boolean alt = true;
        for (int i=0 ; i<lines.size(); i++) {
            System.out.print("*");
            line = lines.get(i);
            int startPos = (maxLine-line.length())/2;

            for (int j=0 ; j<maxLine ; j++) {
                if(j<startPos){
                    System.out.print(" ");
                    if ((maxLine-line.length())%2 == 1) {
                        if (!alt)
                            System.out.print(" ");
                    }
                }
                else if(j==startPos){
                    System.out.print(line);
                    j += (line.length()-1);
                }
                else {
                    System.out.print(" ");
                    if ((maxLine-line.length())%2 == 1) {
                        if (alt)
                            System.out.print(" ");
                            alt = !alt;
                    }
                }
            }
            System.out.println("*");
        }

        for (int i=0 ; i<maxLine+2 ; ++i)
            System.out.print("*");
        System.out.println();
        input.close();
    }
}


import java.io.*;
import java.util.*;

public class CenterAllignment {

    public static void main(String[] args) throws java.lang.Exception {

        BufferedReader input = new BufferedReader(new InputStreamReader(System.in));
        ArrayList<String> lines = new ArrayList<String>();
        int maxLine = 0;
        String line = new String();

        while ((line = input.readLine()) != null)
        {
                maxLine = Math.max(maxLine, line.length());
                lines.add(line);
        }

        for (int i=0 ; i<maxLine+2 ; ++i)
            System.out.print("*");
        System.out.println();

        boolean alt = true;
        for (int i=0 ; i<lines.size(); i++) {
            System.out.print("*");
            line = lines.get(i);
            int startPos = (maxLine-line.length())/2;

            if ((maxLine-line.length())%2 == 1) {
                if (!alt)
                    ++startPos;
                alt = !alt;
            }

            for (int j=0 ; j<startPos ; j++) {
                System.out.print(" ");
            System.out.print(line);
            for (int k=startPos+line.length() ; k<maxLine ; j++)
                System.out.print(" ");
            }
            System.out.println("*");
        }

        for (int i=0 ; i<maxLine+2 ; ++i)
            System.out.print("*");
        System.out.println();

    }
}


import java.util.*;

public class CenterAllignment {

    public static void main(String[] args) throws java.lang.Exception {

        Scanner input = new Scanner(System.in);
        ArrayList<String> lines = new ArrayList<String>();
        int maxLine = 0;
        String line = new String();

        while (input.hasNextLine())
        {
            line = input.nextLine();
            maxLine = Math.max(maxLine, line.length());
            lines.add(line);
        }

        for (int i=0 ; i<maxLine+2 ; ++i)
            System.out.print("*");
        System.out.println();

        boolean alt = true;
        for (int i=0 ; i<lines.size(); i++) {
            System.out.print("*");
            line = lines.get(i);
            int startPos = (maxLine-line.length())/2;

            for (int j=0 ; j<startPos ; j++)
                System.out.print(" ");
            if (startPos%2 == 1) {
                if (!alt)
                    System.out.print(" ");
            }

            System.out.print(line);

            for (int j=0 ; j<startPos ; j++)
                System.out.print(" ");
            if (startPos%2 == 1) {
                if (alt)
                    System.out.print(" ");
                alt = !alt;
            }
            System.out.println("*");
        }

        for (int i=0 ; i<maxLine+2 ; ++i)
            System.out.print("*");
        System.out.println();
        input.close();
    }
}


import java.io.*;
import java.util.*;

public class CenterAllignment {

    public static void main(String[] args) throws java.lang.Exception {

        BufferedReader input = new BufferedReader(new InputStreamReader(System.in));
        ArrayList<String> lines = new ArrayList<String>();
        int maxLine = 0;
        String line = new String();

        while ((line = input.readLine()) != null)
        {
                maxLine = Math.max(maxLine, line.length());
                lines.add(line);
        }

        for (int i=0 ; i<maxLine+2 ; ++i)
            System.out.print("*");
        System.out.println();

        boolean alt = true;
        for (int i=0 ; i<lines.size(); i++) {
            System.out.print("*");
            line = lines.get(i);
            int startPos = (maxLine-line.length())/2;

            if ((maxLine-line.length())%2 == 1) {
                if (!alt)
                    ++startPos;
                alt = !alt;
            }

            for (int j=0 ; j<maxLine ; j++) {
                if(j<startPos)
                    System.out.print(" ");
                else if(j==startPos) {
                    System.out.print(line);
                    j = startPos+line.length()-1;
                }
                else
                    System.out.print(" ");
            }
            System.out.println("*");
        }

        for (int i=0 ; i<maxLine+2 ; ++i)
            System.out.print("*");
        System.out.println();

    }
}


import java.util.*;

public class CenterAllignment {

    public static void main(String[] args) throws java.lang.Exception {

        Scanner input = new Scanner(System.in);
        ArrayList<String> lines = new ArrayList<String>();
        int maxLine = 0;
        String line = new String();

        while (input.hasNextLine())
        {
            line = input.nextLine();
            maxLine = Math.max(maxLine, line.length());
            lines.add(line);
        }

        for (int i=0 ; i<maxLine+2 ; ++i)
            System.out.print("*");
        System.out.println();

        boolean alt = true;
        for (int i=0 ; i<lines.size(); i++) {
            System.out.print("*");
            line = lines.get(i);
            int startPos = (maxLine-line.length())/2;

            if ((maxLine-line.length())%2 == 1) {
                if (!alt)
                    ++startPos;
                alt = !alt;
            }

            for (int j=0 ; j<maxLine ; j++) {
                if(j<startPos)
                    System.out.print(" ");
                else if(j==startPos){
                    System.out.print(line);
                    j += (line.length()-1);
                }
                else
                    System.out.print(" ");
            }
            System.out.println("*");
        }

        for (int i=0 ; i<maxLine+2 ; ++i)
            System.out.print("*");
        System.out.println();
        input.close();
    }
}


import java.io.*;
import java.util.*;

public class CenterAllignment {

    public static void main(String[] args) throws java.lang.Exception {

        BufferedReader input = new BufferedReader(new InputStreamReader(System.in));
        ArrayList<String> lines = new ArrayList<String>();
        int maxLine = 0;
        String line = new String();

        while ((line = input.readLine()) != null)
        {
                maxLine = Math.max(maxLine, line.length());
                lines.add(line);
        }

        for (int i=0 ; i<maxLine+2 ; ++i)
            System.out.print("*");
        System.out.println();

        boolean alt = true;
        for (int i=0 ; i<lines.size(); i++) {
            System.out.print("*");
            line = lines.get(i);
            int startPos = (maxLine-line.length())/2;

            if ((maxLine-line.length())%2 == 1) {
                if (!alt)
                    ++startPos;
                alt = !alt;
            }

            for (int j=0 ; j<maxLine ; j++) {
                if(j<startPos)
                    System.out.print(" ");
                else if(j>=startPos && j<(startPos+line.length()))
                    System.out.print(line.charAt(j-startPos));
                else
                    System.out.print(" ");
            }
            System.out.println("*");
        }

        for (int i=0 ; i<maxLine+2 ; ++i)
            System.out.print("*");
        System.out.println();

    }
}


#include <map>
#include <set>
#include <cmath>
#include <queue>
#include <stack>
#include <cstdio>
#include <vector>
#include <string>
#include <utility>
#include <cstring>
#include <iostream>
#include <algorithm>

using namespace std;
typedef pair<int,int> PII;
typedef long long ll;

const int mod = 10000;
const int inf = 0x3fffffff;
const int maxn =  1e5+10;
const double eps = 1e-10;

vector<int>G[maxn];
int  N,M,vis[maxn];

void init()
{
    memset(vis,0,sizeof(vis));
    for(int i=0;i<maxn;i++) G[i].clear();
}
void add_edge(int u,int v){
    G[u].push_back(v);
    G[v].push_back(u);
}

int DFS(int u,int fa){
    if(vis[u]==1) return 1;//再次访问u点,表示可再用
    else if(vis[u]==2) return 0;//再次访问u点,表示不可再用
    vis[u]=1;//可用
    int last=0;
    for(int i=0;i<(int)G[u].size();i++){
        int v=G[u][i];
        if(G[u][i]==fa) continue;
        int t=DFS(v,u);
        if(!t) continue;
        if(last) printf("%d %d %d\n",last,u,v) , last=0;
        else last=v;
    }
    vis[u]=2;//不可用
    if(last){
        printf("%d %d %d\n",last,u,fa);
        return 0;//此时,首次访问u结束,return 0表示此时不可用
    }
    else return 1;//此时,首次访问u结束,return 1表示还可用一次
}

int main()
{
    //freopen("D://r1.txt","r",stdin);
    //cin.sync_with_stdio();
    while(~scanf("%d%d",&N,&M)){
        init();
        for(int i=0;i<M;i++){
            int u,v; scanf("%d%d",&u,&v);
            add_edge(u,v);
        }
        if(M%2==0) DFS(1,0);
        else puts("No solution");
    }
    return 0;
}


# include <bits/stdc++.h>

using namespace std;

const int maxn = 1e5 + 10;
int n, m;
int mark[maxn];
int par[maxn];
bool finish[maxn];
vector <int> adj[maxn];

void dfs(int v){
	mark[v] = 1;
	for(int i=0 ; i<adj[v].size() ; i++){
		int u = adj[v][i];
		if(!mark[u]){
			par[u] = v;
			dfs(u);
		}
	}

	int back = 0;
	for(int i=0 ; i<adj[v].size() ; i++){
		int u = adj[v][i];
		if((mark[u] == 2 and !finish[u]) or (mark[u] == 1 && u != par[v])){
			if(back != 0){
				cout << back <<" "<< v <<" "<< u << '\n';
				back = 0;
			}
			else
				back = u;
			if(mark[u] == 2 and !finish[u])
				finish[u] = true;
		}
	}

	if(back != 0){
		cout << back <<" "<< v <<" "<< par[v] << '\n';
		finish[v] = true;
	}

	mark[v] = 2;
}

int main(){
	ios_base::sync_with_stdio(false);
	cin.tie(0);
	int n, m;
	cin >> n >> m;
	for(int i=0 ; i<m ; i++){
		int fi, se;
		cin >> fi >> se;
		adj[fi].push_back(se);
		adj[se].push_back(fi);
	}

	if(m % 2)
		cout << "No solution" << endl;
	else
		dfs(1);

	return 0;
}


#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<cmath>
#include<set>
#include<vector>
#include<map>
#include<queue>
#include<deque>
#define mkp make_pair

using namespace std;

typedef long long ll;
typedef pair<int,int> pi;

const int maxn = 100005;
const int inf = 1<<29;
const int mod = 1000000007;
const double eps = 1e-8;

void out(int* dat,int si)
{
    for(int i=1;i<=si;i++)
        printf("%d%c",dat[i],i==si?'\n':' ');
}

struct edge
{
    int next,to;
}ji[maxn<<1];

int head[maxn],tot,n,m;
bool vis[maxn],block[maxn<<1];

void add(int x,int y)
{
    ji[tot].next = head[x];
    ji[tot].to = y;
    head[x] = tot++;
}

int dfs(int x)
{
    vis[x] = 1;
    vector<int> v,f;
    for(int k=head[x];k!=-1;k=ji[k].next)
    {
        if(!block[k])
        {
            block[k] = block[k^1] = 1;
            f.push_back(ji[k].to);
        }
    }
    for(int i=0;i<f.size();i++)
    {
        int tp = dfs(f[i]);
        if(tp)
            printf("%d %d %d\n",x,f[i],tp);
        else
            v.push_back(f[i]);
    }
    for(int i=1;i<v.size();i+=2)
        printf("%d %d %d\n",v[i-1],x,v[i]);
    return (v.size()&1)?v[v.size()-1]:0;
}

int main()
{
    int a,b;
    memset(head,-1,sizeof(head));
    scanf("%d%d",&n,&m);
    for(int i=0;i<m;i++)
    {
        scanf("%d%d",&a,&b);
        add(a,b);add(b,a);
    }
    if(m&1)
    {
        puts("No solution");
        return 0;
    }
    for(int i=1;i<=n;i++)
        if(!vis[i])
            dfs(i);
}


#include <iostream>
#include <cstring>
#include <cstdio>
#include <vector>

#define Maxn 200010

using namespace std;

int head[Maxn];

struct Node
{
	int u,v;
	int next;
}edge[Maxn];

int n,m;

int dfs(int u)
{
	vector<int> q;
	vector<int> adj;
	for(int i=head[u];i!=-1;i=edge[i].next)
	{
		int v=edge[i].v;
		for(int j=head[v];j!=-1;j=edge[j].next)
		{
			if(j==head[v] && edge[j].v==u)
			{
				head[v]=edge[j].next;
				edge[j].next=-1;
				break;
			}
			else if(edge[edge[j].next].v==u)
			{
				edge[j].next=edge[edge[j].next].next;
				edge[edge[j].next].next=-1;
				break;
			}
		}
		adj.push_back(v);
	}
	head[u]=-1;
	while(adj.size())
	{
		int v,w;
		v=adj.back();
		adj.pop_back();
		w=dfs(v);
		if(!w) q.push_back(v);
		else printf("%d %d %d\n",u,v,w);
	}
	while(q.size()>=2)
	{
		int v=q.back();
		q.pop_back();
		int w=q.back();
		q.pop_back();
		printf("%d %d %d\n",v,u,w);
	}
	if(!q.size()) return 0;
	else return q.back();
}

int main()
{
	scanf("%d%d",&n,&m);
	memset(head,-1,sizeof(head));
	int cnt=0;
	int u,v;
	if(m&1)
	{
		puts("No solution");
		return 0;
	}
	for(int i=0;i<m;++i)
	{
		scanf("%d%d",&u,&v);
		edge[cnt].u=u;
		edge[cnt].v=v;
		edge[cnt].next=head[u];
		head[u]=cnt++;
		edge[cnt].u=v;
		edge[cnt].v=u;
		edge[cnt].next=head[v];
		head[v]=cnt++;
	}
	dfs(1);
	return 0;
}


#include <iostream>
#include <cstring>
#include <cstdio>
#include <vector>

#define Maxn 100005

using namespace std;

int head[Maxn];

struct Node
{
	int u,v;
	int next;
}edge[Maxn];

int n,m;

int dfs(int u)
{
	vector<int> q;
	vector<int> adj;
	for(int i=head[u];i!=-1;i=edge[i].next)
	{
		int v=edge[i].v;
		head[v]=-1;
		adj.push_back(v);
	}
	head[u]=-1;
	while(adj.size())
	{
		int v,w;
		v=adj.back();
		adj.pop_back();
		w=dfs(v);
		if(!w) q.push_back(v);
		else printf("%d %d %d\n",u,v,w);
	}
	while(q.size()>=2)
	{
		int v=q.back();
		q.pop_back();
		int w=q.back();
		q.pop_back();
		printf("%d %d %d\n",v,u,w);
	}
	if(!q.size()) return 0;
	else return q.back();
}

int main()
{
	scanf("%d%d",&n,&m);
	memset(head,-1,sizeof(head));
	int cnt=0;
	int u,v;
	if(m&1)
	{
		puts("No solution");
		return 0;
	}
	for(int i=0;i<m;++i)
	{
		scanf("%d%d",&u,&v);
		edge[cnt].u=u;
		edge[cnt].v=v;
		edge[cnt].next=head[u];
		head[u]=cnt++;
		edge[cnt].u=v;
		edge[cnt].v=u;
		edge[cnt].next=head[v];
		head[v]=cnt++;
	}
	dfs(1);
	return 0;
}


#include <iostream>
#include <cstring>
#include <cstdio>
#include <vector>

#define Maxn 100005

using namespace std;

int head[Maxn];

struct Node
{
	int u,v;
	int next;
}edge[Maxn];

int n,m;

int dfs(int u)
{
	vector<int> q;
	vector<int> adj;
	for(int i=head[u];i!=-1;i=edge[i].next)
	{
		int v=edge[i].v;
		for(int j=head[v];j!=-1;j=edge[j].next)
		{
			if(j==head[v] && edge[j].v==u)
			{
				head[v]=edge[j].next;
				edge[j].next=-1;
				break;
			}
			else if(edge[edge[j].next].v==u)
			{
				edge[j].next=edge[edge[j].next].next;
				edge[edge[j].next].next=-1;
				break;
			}
		}
		adj.push_back(v);
	}
	head[u]=-1;
	while(adj.size())
	{
		int v,w;
		v=adj.back();
		adj.pop_back();
		w=dfs(v);
		if(!w) q.push_back(v);
		else printf("%d %d %d\n",u,v,w);
	}
	while(q.size()>=2)
	{
		int v=q.back();
		q.pop_back();
		int w=q.back();
		q.pop_back();
		printf("%d %d %d\n",v,u,w);
	}
	if(!q.size()) return 0;
	else return q.back();
}

int main()
{
	scanf("%d%d",&n,&m);
	memset(head,-1,sizeof(head));
	int cnt=0;
	int u,v;
	if(m&1)
	{
		puts("No solution");
		return 0;
	}
	for(int i=0;i<m;++i)
	{
		scanf("%d%d",&u,&v);
		edge[cnt].u=u;
		edge[cnt].v=v;
		edge[cnt].next=head[u];
		head[u]=cnt++;
		edge[cnt].u=v;
		edge[cnt].v=u;
		edge[cnt].next=head[v];
		head[v]=cnt++;
	}
	dfs(1);
	return 0;
}


#include <iostream>
#include <string>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <vector>
#include <set>
#include <map>
#include <deque>
#include <stack>
#include <queue>
#include <algorithm>

using std::vector;

const int MAX_V = 100000+1;
int n, m;
// bool BG[MAX_V][MAX_V];

std::vector<int> G[MAX_V];

int dfs(int v){
	// find set of u
	std::vector<int> adj_set;
	for (std::vector<int>::iterator i = G[v].begin(); i != G[v].end(); )
	{

		adj_set.push_back(*i);
		// BG[v][*i] = false;
		// BG[*i][v] = false;
		for (std::vector<int>::iterator j = G[*i].begin(); j != G[*i].end(); ++j)
		{
			if (*j == v)
			{
				// printf("remove u-v %d\n", *j);
				G[*i].erase(j);
				break;
			}
		}
		// printf("remove v-u %d\n", *i);
		i = G[v].erase(i);

	}

	std::vector<int> unpair;
	// step in and find w from each u
	// printf("size %lu\n", adj_set.size());
	while(adj_set.size()){

		int u = adj_set.back();
		// printf("adj %d\n", u);
		adj_set.pop_back();
		int w = dfs(u);
		if (w==0)
		{
			/*v-u unpair*/
			unpair.push_back(u);
		}else{
			/*v-u-w can be pair*/
			printf("%d %d %d\n", v, u, w);
		}
	}

	while (unpair.size()>=2)
	{
		int u = unpair.back();
		unpair.pop_back();
		int w = unpair.back();
		unpair.pop_back();
		printf("%d %d %d\n", u, v, w);
	}
	if (unpair.size()==0)
	{
		return 0;
	}else{
		return unpair.back();
	}
}

int main(){
	scanf("%d %d", &n, &m);
	int from, to;
	for (int i = 0; i < m; ++i)
	{
		scanf("%d%d", &from, &to);
		G[from].push_back(to);
		G[to].push_back(from);
		// BG[from][to] = true;
		// BG[to][from] = true;
	}
	if (m%2)
	{
		printf("%s\n", "No solution");
	}else{
		dfs(1);
	}

	return 0;
}


#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;

int getx(int &x){
  x=0;char c;
  for(c=getchar();c<'0'||c>'9';c=getchar());
  for(;c>='0'&&c<='9';c=getchar())x=x*10+c-'0';
  return x;
}

const int maxn=100050;
int n,m;
int first[maxn],next[maxn*2],to[maxn*2],f[maxn*2],size=1;

void put(int x,int y){
  next[++size]=first[x];
  first[x]=size;
  to[size]=y;
}

int dfn[maxn],tot;
int line[maxn],wei;

int dfs(int pre,int v){
  dfn[v]=++tot;
//  printf("dfs(%d)\n",v);
  for(int k=first[v];k;k=next[k])
    if(!dfn[to[k]]){
      int t=dfs(v,to[k]);
      if(t){
        printf("%d %d %d\n",v,to[k],to[t]);
        f[k]=1;f[k^1]=1;
        f[t]=1;f[t^1]=1;
      }
    }
  //printf("v=%d\n",v);
  wei=0;
  for(int k=first[v];k;k=next[k])
    if(f[k]==0&&to[k]!=pre) line[++wei]=k;
 // printf("wei=%d\n",wei);
 // for(int i=1;i<=wei;i++)
  //  printf("%d ",to[line[i]]);printf("\n");
  for(int i=1;i<=wei/2;i++){
    f[line[2*i-1]]=1;f[line[2*i-1]^1]=1;
    f[line[2*i]]=1;f[line[2*i]^1]=1;
    printf("%d %d %d\n",to[line[2*i-1]],v,to[line[2*i]]);
  }
  int ret=0;
  if(wei&1) ret=line[wei];
  //printf("v=%d\n",v);
 // printf("return %d to[%d]=%d\n",ret,ret,to[ret]);
  return ret;
}

int main(){
   // freopen("E.in","r",stdin);
   // freopen("E.out","w",stdout);
   getx(n),getx(m);
   for(int i=1;i<=m;i++){
     int x,y;getx(x),getx(y);
     put(x,y);
     put(y,x);
   }
   if(m&1) {printf("No solution");return 0;}
   dfs(0,1);
}


#include <cstdio>

#define N 100000

bool a[N * 2 + 1], aa[N + 1];
int b[N * 2 + 1], c[N * 2 + 1], h[N + 1], n, m, i, x, y;

int go(int k)
{
	aa[k] = 1;
	int i, t, x = 0;
	for (i = h[k]; i; i = b[i])
		if (!a[i])
		{
			a[i > m ? i - m : i + m] = 1;
			if (t = aa[c[i]] ? 0 : go(c[i]))
				printf("%d %d %d\n", k, c[i], t);
			else
				if (x)
					printf("%d %d %d\n", x, k, c[i]), x = 0;
				else
					x = c[i];
		}

	return x;
}

int main()
{
	scanf("%d%d", &n, &m);

	if (m & 1)
	{
		puts("No solution");
		return 0;
	}

	for (i = 1; i <= m; ++i)
	{
		scanf("%d%d", &x, &y);
		b[i] = h[x];
		c[i] = y;
		h[x] = i;
		b[i + m] = h[y];
		c[i + m] = x;
		h[y] = i + m;
	}

	go(1);

	return 0;
}


#include <cstdio>
#include <vector>
#include <cstring>
#include <functional>
#include <algorithm>
#include <math.h>
#include <bitset>
#include <set>
#include <queue>
#include <iostream>
#include <string>
#include <sstream>
#include <stack>
#include <complex>
#include <numeric>
#include <map>
#include <time.h>
using namespace std;
typedef long double ld;
typedef long long ll;
typedef unsigned long long ull;
typedef unsigned int uint;
typedef pair<int,int> pii;
typedef pair<int,ll> pil;
typedef pair<int,ull> piu;
typedef pair<ll,int> pli;
typedef pair<ll,ll> pll;
typedef pair<pii,ll> ppl;
typedef pair<ll,pii> plp;
typedef pair<int,pii> pip;
typedef pair<pii,int> ppi;
typedef pair<pii,pii> ppp;
typedef pair<double,int> pdi;
typedef pair<int,double> pid;
typedef pair<double,pii> pdp;
typedef pair<double,double> pdd;
typedef pair<pdd,double> pd3;
typedef vector<int> vec;
typedef vector<vec> mat;
#define rep(i,n) for (int (i) = 0; (i) < (n); (i)++)
#define repn(i,a,n) for (int (i) = (a); (i) < (n); (i)++)
#define ALL(x) (x).begin(),(x).end()
#define pb push_back
#define SORT(x) sort((x).begin(),(x).end())
#define SORTN(x,n) sort((x),(x)+(n))
#define ERASE(x) (x).erase(unique((x).begin(),(x).end()),(x).end())
#define COUNT(x,c) count((x).begin(),(x).end(),(c))
#define REMOVE(x,c) (x).erase(remove((x).begin(),(x).end(),(c)),(x).end())
#define REVERSE(x) reverse((x).begin(),(x).end())
#define FORIT(it,v) for(__typeof((v).begin()) it=(v).begin();it!=(v).end();it++)
#define LB(x,a) lower_bound((x).begin(),(x).end(),(a))-(x).begin()
#define lb(x,a) lower_bound((x).begin(),(x).end(),(a))
#define LBN(x,a,n) lower_bound((x),(x)+(n),(a))-(x)
#define lbN(x,a,n) lower_bound((x),(x)+(n),(a))
#define UB(x,a) upper_bound((x).begin(),(x).end(),(a))-(x).begin()
#define ub(x,a) upper_bound((x).begin(),(x).end(),(a))
#define BS(x,a) binary_search((x).begin(),(x).end(),(a))
#define BS2(x,n,a) binary_search((x),(x)+(n),(a))
#define NB(x) (((x)&~((x)+((x)&-(x))))/((x)&-(x))>>1)|((x)+((x)&-(x)))
#define NP(x) next_permutation((x).begin(),(x).end())
#define MM(x,p) memset((x),(p),sizeof(x))
#define SQ(x) (x)*(x)
#define SC(c1,c2) strcmp(c1,c2)==0
#define mp make_pair
#define INF (1<<30)
#define INFL (1LL<<61)
#define fi first
#define se second
#define MOD 1000000007
#define EPS 1e-8
#define MIN(x,a) x=min(x,a)
#define MAX(x,a) x=max(x,a)
#define madd(x,a) x=(x+a)%MOD
#define msub(x,a) x=(x+MOD-a)%MOD
#define OUTPUT(x) rep(i,x.size())printf("%d%c",x[i],i+1==x.size()?'\n':' ');

int N,M;
int A[100000],B[100000];
vector<pii> G[114514];
bool fe[100000];
bool fv[100000];

void output(int a,int b)
{
    if(A[a]==A[b])printf("%d %d %d\n",B[a]+1,A[a]+1,B[b]+1);
    if(A[a]==B[b])printf("%d %d %d\n",B[a]+1,A[a]+1,A[b]+1);

    if(B[a]==A[b])printf("%d %d %d\n",A[a]+1,B[a]+1,B[b]+1);
    if(B[a]==B[b])printf("%d %d %d\n",A[a]+1,B[a]+1,A[b]+1);
}

int solve(int v)
{
    if(fv[v])return -1;
    fv[v]=true;
    vector<int> lis;
    rep(i,G[v].size())if(!fe[G[v][i].fi])
    {
        fe[G[v][i].fi]=true;
        int tt=solve(G[v][i].se);
        if(tt==-1)lis.pb(G[v][i].fi);
        else output(G[v][i].fi,tt);
    }
    rep(i,lis.size()/2)output(lis[i*2],lis[i*2+1]);
    if(lis.size()%2==0)return -1;
    return lis.back();
}

int main()
{
    scanf("%d%d",&N,&M);
    rep(i,M)
    {
        scanf("%d%d",&A[i],&B[i]),A[i]--,B[i]--;
        G[A[i]].pb(mp(i,B[i]));
        G[B[i]].pb(mp(i,A[i]));
    }
    if(M%2==1)return puts("No solution"),0;
    solve(0);
}


#include <algorithm>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <map>
#include <queue>
#define N 200010
#define For(i,x,y) for (i=x;i<=y;i++)
using namespace std;
int i,j,k,n,m,x,y,t;
int a[N],next[N],head[N],F[N];
map<int,int> M[N];
priority_queue<int> q[N];
inline void add(int x,int y) {
	a[++t]=y,next[t]=head[x],head[x]=t;
	a[++t]=x,next[t]=head[y],head[y]=t;
}
int dfs(int x) {
	int v,i;
	if (F[x]) return 0;
	F[x]=1;
	for (v=head[x];v;v=next[v])
	if (!M[x].count(a[v])) M[x][a[v]]=M[a[v]][x]=x;
	for (v=head[x];v;v=next[v])
	if (M[x][a[v]]==x) {
		int w=dfs(a[v]);
		if (w) printf("%d %d %d\n",x,a[v],w);
		else q[x].push(a[v]);
	}
	int A=0;
	for (;!q[x].empty();) {
		A=q[x].top();
		q[x].pop();
		if (q[x].empty()) break;
		int B=q[x].top();
		printf("%d %d %d\n",A,x,B);
		q[x].pop(); A=0;
	}
	return A;
}
int main() {
	scanf("%d%d",&n,&m);
	if (m&1) {
		printf("No solution\n");
		return 0;
	}
	For(i,1,m) scanf("%d%d",&x,&y),add(x,y);
	dfs(1);
	//for(;;);
	return 0;
}


#include <algorithm>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <map>
#include <queue>
#define N 200010
#define For(i,x,y) for (i=x;i<=y;i++)
using namespace std;
int i,j,k,n,m,x,y,t;
int a[N],next[N],head[N];
map<int,int> M[N];
priority_queue<int> q[N];
inline void add(int x,int y) {
	a[++t]=y,next[t]=head[x],head[x]=t;
	a[++t]=x,next[t]=head[y],head[y]=t;
}
int dfs(int x) {
	int v;
	for (v=head[x];v;v=next[v])
	if (!M[x].count(a[v])) M[x][a[v]]=M[a[v]][x]=x;
	for (v=head[x];v;v=next[v])
	if (M[x][a[v]]==x) {
		int w=dfs(a[v]);
		if (w) printf("%d %d %d\n",x,a[v],w);
		else q[x].push(a[v]);
	}
	int A=0;
	for (;!q[x].empty();) {
		A=q[x].top();
		q[x].pop();
		if (q[x].empty()) break;
		int B=q[x].top();
		printf("%d %d %d\n",A,x,B);
		q[x].pop(); A=0;
	}
	return A;
}
int main() {
	scanf("%d%d",&n,&m);
	if (m&1) {
		printf("No solution\n");
		return 0;
	}
	For(i,1,m) scanf("%d%d",&x,&y),add(x,y);
	dfs(1);
	//for(;;);
	return 0;
}


#include <algorithm>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <map>
#include <queue>
#define N 200010
#define For(i,x,y) for (i=x;i<=y;i++)
using namespace std;
int i,j,k,n,m,x,y,t;
int a[N],next[N],head[N];
map<int,int> M[N];
priority_queue<
inline void add(int x,int y) {
	a[++t]=x,next[t]=head[x],head[x]=t;
	a[++t]=y,next[t]=head[y],head[y]=t;
}
int dfs(int x) {
	int v;
	for (v=head[x];v;v=next[v])
	if (!M[x].count(a[v])) M[x][a[v]]=x;
	for (v=head[x];v;v=next[v])
	if (M[x][a[v]]==x) {
		int w=dfs(a[v]);
		if (w) printf("%d %d %d\n",x,a[v],w);
		else
	}

}
int main() {
	scanf("%d%d",&n,&m);
	if (m&1) {
		printf("No solution\n");
		return 0;
	}
	For(i,1,m) scanf("%d%d",&x,&y),add(x,y);
	dfs(1);
	return 0;
}


#include <bits/stdc++.h>
using namespace std;
typedef vector<int> vi;
typedef pair<int, int> ii;
typedef vector<ii> vii;

vi graph[100010];
map<ii, int> mp;
bitset<100010> visNode, visEdge;
int n, m, a, b;

ii dfs(int node) {
    vi edges;
    for(int i = 0; i < graph[node].size(); i++) {
        ii tmpEdge(-1, -1);
        ii secondEdge(-1, -1);
        int u = min(node, graph[node][i]);
        int v = max(node, graph[node][i]);

        if (visEdge[mp[ii(u, v)]]) { continue; }

        tmpEdge = ii(node, graph[node][i]);
        visEdge[mp[ii(u, v)]] = 1;

        if (!visNode[graph[node][i]]) {
            visNode[graph[node][i]] = 1;
            secondEdge = dfs(graph[node][i]);
        }

        if (secondEdge.first != -1) {
            int thirdNode = (secondEdge.first == graph[node][i])?secondEdge.second:secondEdge.first;
            printf("%d %d %d\n", node+1, graph[node][i]+1, thirdNode+1);
        } else {
            edges.push_back(tmpEdge.second);
        }
    }
    for(int i = 0; i+1 < edges.size(); i+=2) {
        printf("%d %d %d\n", edges[i]+1, node+1, edges[i+1]+1);
    }
    if (edges.size() %2 == 0) return ii(-1, -1);
    else return ii(min(node, edges[edges.size()-1]), max(node, edges[edges.size()-1]));
}

int main() {
    scanf("%d %d", &n, &m);
    if (m % 2 == 1) {
        printf("No solution\n");
        return 0;
    }
    for(int i = 0; i < m; i++) {
        scanf("%d %d", &a, &b);
        a--, b--;
        graph[a].push_back(b);
        graph[b].push_back(a);
        mp[ii(min(a, b), max(a, b))] = i;
    }
    visNode[0] = 1;
    dfs(0);
}


#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cassert>
#include <cmath>
#include <algorithm>
#include <vector>
#include <string>
#include <map>
#include <set>
using namespace std;
typedef long long LL;
typedef pair <int, int> PII;
const int INF=1e8;
const int MN=1e5+7;
int n,m,d[MN];
vector <int> E[MN],H[MN];
int a[MN],b[MN],c[MN],t=0;

int dfs(int u, int pre){
    for (int i=0; i<E[u].size(); i++){
        int v=E[u][i];
        if (d[v]==0){
            d[v]=d[u]+1;
            if (dfs(v,u)) H[u].push_back(v);
        }
        else
        if (v!=pre && d[v]<d[u]) H[u].push_back(v);
    }
    int i=0;
    while (i+1<H[u].size()){
        a[++t]=H[u][i]; b[t]=u; c[t]=H[u][i+1];
        i+=2;
    }
    /*for (int i=0; i<H[u].size()-1; i+=2){
        a[++t]=H[u][i]; b[t]=u; c[t]=H[u][i+1];
    }*/
    if (H[u].size()&1){
        a[++t]=H[u].back(); b[t]=u; c[t]=pre;
        return 0;
    }
    return 1;
}

int main(){
    scanf("%d%d",&n,&m);
    for (int i=1; i<=m; i++){
        int x,y;
        scanf("%d%d",&x,&y);
        E[x].push_back(y);
        E[y].push_back(x);
    }
    if (m%2){ puts("No solution"); return 0; }
    d[1]=1;
    dfs(1,0);
    for (int i=1; i<=t; i++)
        printf("%d %d %d\n",a[i],b[i],c[i]);
    return 0;
}


#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cassert>
#include <cmath>
#include <algorithm>
#include <vector>
#include <string>
#include <map>
#include <set>
using namespace std;
typedef long long LL;
typedef pair <int, int> PII;
const int INF=1e8;
const int MN=1e5+7;
int n,m,d[MN];
vector <int> E[MN],H[MN];
int a[MN],b[MN],c[MN],t=0;

int dfs(int u, int pre){
    for (int i=0; i<E[u].size(); i++){
        int v=E[u][i];
        if (d[v]==0){
            d[v]=d[u]+1;
            if (dfs(v,u)) H[u].push_back(v);
        }
        else
        if (v!=pre && d[v]<d[u]) H[u].push_back(v);
    }
    for (int i=0; i+1<H[u].size(); i+=2){
        a[++t]=H[u][i]; b[t]=u; c[t]=H[u][i+1];
    }
    if (H[u].size()&1){
        a[++t]=H[u].back(); b[t]=u; c[t]=pre;
        return 0;
    }
    return 1;
}

int main(){
    scanf("%d%d",&n,&m);
    for (int i=1; i<=m; i++){
        int x,y;
        scanf("%d%d",&x,&y);
        E[x].push_back(y);
        E[y].push_back(x);
    }
    if (m%2){ puts("No solution"); return 0; }
    d[1]=1;
    dfs(1,0);
    for (int i=1; i<=t; i++)
        printf("%d %d %d\n",a[i],b[i],c[i]);
    return 0;
}


#include <iostream>
#include <vector>
#include <cstdio>
#include <map>

using namespace std;
typedef pair<int, int> pii;

const int MAXN = 1e5 + 10;

vector<int> G[MAXN];
int ans[MAXN][3], ansN;
map<pii, bool> used;
bool vis[MAXN];

void inline use (int a, int b){
    used[pii(b,a)] = used[pii(a,b)] = true;
}

int dfs(int u){
    vis[u] = true;
    vector<int> rem;

    for (int i = 0; i < G[u].size(); i++){
        int v = G[u][i];

        if (used[pii(u,v)]) continue;
        use(u, v);

        int temp = -1;
        if (!vis[v]) temp = dfs(v);
        if (temp != -1){
            ans[ansN][0] = u;
            ans[ansN][1] = v;
            ans[ansN][2] = temp;
            ansN++;

        }else
            rem.push_back(v);
    }

    int remN = rem.size();

    for (int i = 1; i < remN - (remN % 2); i += 2){
        ans[ansN][0] = rem[i-1];
        ans[ansN][1] = u;
        ans[ansN][2] = rem[i];
        ansN++;
    }

    if (remN % 2)
        return rem[remN - 1];
    else return -1;
}

int main(){
    ios:: sync_with_stdio(0);
    int n, m; scanf("%d%d", &n, &m);

    if (m % 2){
        printf("No solution");
        return 0;
    }

    for (int i = 0; i < m; i++){
        int a, b; scanf("%d%d", &a, &b); a--; b--;
        G[a].push_back(b);
        G[b].push_back(a);
    }

    dfs(0);
    for (int i = 0; i < ansN; i++)
        printf("%d %d %d\n", ans[i][0] + 1, ans[i][1] + 1, ans[i][2] + 1);
}


#include <iostream>
#include <vector>
#include <cstdio>
#include <map>

using namespace std;
typedef pair<int, int> pii;

const int MAXN = 1e5 + 10;

vector<int> G[MAXN];
int ans[MAXN][3], ansN;
map<pii, bool> used;

void inline use (int a, int b){
    used[pii(b,a)] = used[pii(a,b)] = true;
}

int dfs(int u){
    vector<int> rem;

    for (int i = 0; i < G[u].size(); i++){
        int v = G[u][i];

        if (used[pii(u,v)]) continue;
        use(u, v);

        int temp = dfs(v);
        if (temp != -1){
            ans[ansN][0] = u;
            ans[ansN][1] = v;
            ans[ansN][2] = temp;
            ansN++;

        }else
            rem.push_back(v);
    }

    int remN = rem.size();

    for (int i = 1; i < remN - (remN % 2); i += 2){
        ans[ansN][0] = rem[i-1];
        ans[ansN][1] = u;
        ans[ansN][2] = rem[i];
        ansN++;
    }

    if (remN % 2)
        return rem[remN - 1];
    else return -1;
}

int main(){
    ios:: sync_with_stdio(0);
    int n, m; scanf("%d%d", &n, &m);

    if (m % 2){
        printf("No solution");
        return 0;
    }

    for (int i = 0; i < m; i++){
        int a, b; scanf("%d%d", &a, &b); a--; b--;
        G[a].push_back(b);
        G[b].push_back(a);
    }

    dfs(0);
    for (int i = 0; i < ansN; i++)
        printf("%d %d %d\n", ans[i][0] + 1, ans[i][1] + 1, ans[i][2] + 1);
}


#include <iostream>
#include <vector>
#include <map>

using namespace std;
typedef pair<int, int> pii;

const int MAXN = 1e5 + 10;

vector<int> G[MAXN];
int ans[MAXN][3], ansN;
map<pii, bool> used;

void inline use (int a, int b){
    used[pii(b,a)] = used[pii(a,b)] = true;
}

int dfs(int u){
    vector<int> rem;

    for (int i = 0; i < G[u].size(); i++){
        int v = G[u][i];

        if (used[pii(u,v)]) continue;
        use(u, v);

        int temp = dfs(v);
        if (temp != -1){
            ans[ansN][0] = u;
            ans[ansN][1] = v;
            ans[ansN][2] = temp;
            ansN++;

        }else
            rem.push_back(v);
    }

    int remN = rem.size();

    for (int i = 1; i < remN - (remN % 2); i += 2){
        ans[ansN][0] = rem[i-1];
        ans[ansN][1] = u;
        ans[ansN][2] = rem[i];
        ansN++;
    }

    if (remN % 2)
        return rem[remN - 1];
    else return -1;
}

int main(){
    ios:: sync_with_stdio(0);
    int n, m; cin >> n >> m;

    if (m % 2){
        cout << "No solution";
        return 0;
    }

    for (int i = 0; i < m; i++){
        int a, b; cin >> a >> b; a--; b--;
        G[a].push_back(b);
        G[b].push_back(a);
    }

    dfs(0);
    for (int i = 0; i < ansN; i++)
        cout << ans[i][0] + 1 << " " << ans[i][1] + 1 << " " << ans[i][2] + 1<< "\n";
}


#include <iostream>
#include <vector>
#include <map>

using namespace std;
typedef pair<int, int> pii;

const int MAXN = 1e5 + 10;

vector<int> G[MAXN];
int ans[MAXN][3], ansN;
vector<int> rem[MAXN];
map<pii, bool> used;

int dfs(int u){

    int remN = rem[u].size();
    int l = remN, r = remN;

    for (int i = 0; i < G[u].size(); i++){
        pii e = pii(u, G[u][i]);
        if (used[e]) continue;
        used[e] = used[pii(e.second, e.first)] = true;

        int temp = dfs(e.second);
        if (temp != -1){
            ans[ansN][0] = u;
            ans[ansN][1] = e.second;
            ans[ansN][2] = temp;
            ansN++;
        }else
            rem[u].push_back(e.second), r++;
    }

    remN = r - l;
    for (int i = 1; i < remN - (remN % 2); i += 2){
        ans[ansN][0] = rem[u][l+i-1];
        ans[ansN][1] = u;
        ans[ansN][2] = rem[u][l+i];
        ansN++;
    }

    if (remN % 2)
        return rem[u][l+remN - 1];
    else return -1;
}

int main(){
    ios:: sync_with_stdio(0);
    int n, m; cin >> n >> m;

    if (m % 2){
        cout << "No solution";
        return 0;
    }

    for (int i = 0; i < m; i++){
        int a, b; cin >> a >> b; a--; b--;
        G[a].push_back(b);
        G[b].push_back(a);
        used[pii(a, b)] = used[pii(b,a)] = false;
    }

    dfs(0);
    for (int i = 0; i < ansN; i++)
        cout << ans[i][0] + 1 << " " << ans[i][1] + 1 << " " << ans[i][2] + 1<< "\n";
}


#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<algorithm>
#include<set>
using namespace std;
#define LL long long
#define CL(a) memset(a,0,sizeof(a))
#define N 100010
#define MOD 1000000007
#define eps 1e-9
#define rep(i,n) for(int i=0;i<n;i++)
set<int>g[N];
bool v[N];
int n,m;
void dfs(int x,int p){
	v[x]=1;
	set<int>q=g[x];
	set<int>::iterator it=q.begin();
	for(;it!=q.end();it++)if(!v[*it])dfs(*it,x);
//	cout<<x<<" "<<g[x].size()<<endl;
	if(g[x].size()&1)g[x].erase(p);
	for(it=g[x].begin();it!=g[x].end();){
		printf("%d %d ",*it,x);
		g[*it++].erase(x);
		printf("%d\n",*it);
		g[*it++].erase(x);
	}
//	cout<<x<<" "<<g[x].size()<<endl;
	return;
}
int main(){
	#ifndef ONLINE_JUDGE
	freopen("1.in","r",stdin);
	#endif
	scanf("%d%d",&n,&m);
	rep(i,m){
		int x,y;
		scanf("%d%d",&x,&y);
		g[x].insert(y);
		g[y].insert(x);
	}
	if(m&1){
		printf("No solution\n");
		return 0;
	}
	CL(v);dfs(1,0);
    return 0;
}


#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<algorithm>
#include<set>
using namespace std;
#define LL long long
#define CL(a) memset(a,0,sizeof(a))
#define N 100010
#define MOD 1000000007
#define eps 1e-9
#define rep(i,n) for(int i=0;i<n;i++)
set<int>g[N];
bool v[N];
int n,m;
void dfs(int x,int p){
//	cout<<x<<" "<<g[x].size()<<endl;
	v[x]=1;
	set<int>::iterator it=g[x].begin();
	for(;it!=g[x].end();it++)if(!v[*it])dfs(*it,x);
//	cout<<x<<" "<<g[x].size()<<endl;
	if(g[x].size()&1)g[x].erase(p);
	for(it=g[x].begin();it!=g[x].end();){
		printf("%d %d ",*it,x);
		g[*it].erase(x);it++;
		printf("%d\n",*it);
		g[*it].erase(x);it++;
	}
//	cout<<x<<" "<<g[x].size()<<endl;
}
int main(){
	#ifndef ONLINE_JUDGE
	freopen("1.in","r",stdin);
	#endif
	scanf("%d%d",&n,&m);
	rep(i,m){
		int x,y;
		scanf("%d%d",&x,&y);
		g[x].insert(y);
		g[y].insert(x);
	}
	if(m&1){
		printf("No solution\n");
		return 0;
	}
	CL(v);dfs(1,0);
    return 0;
}


#include <iostream>
#include <algorithm>
#include <cstdio>
using namespace std;
#define maxn 100000+10
int edge[maxn],first[maxn],nxt[maxn/2];
bool v[maxn];
int mark[maxn],vv[maxn/2];

void dfs(int n,int fa)
{
    for(int e=first[n];e;e=nxt[e]) if(vv[e]!=fa && !v[vv[e]])
        dfs(vv[e],n);
    int top = 0;
    for(int e=first[n];e;e=nxt[e]) if(vv[e]!=fa && mark[vv[e]]!=1)
        edge[top++] = vv[e];

    if(top&&1)//top is odd
        edge[top++]=fa,mark[n]=1;
    else
        mark[n]=2;
    for(int i=0;i<top;i+=2)
    {
        printf("%d %d %d\n",edge[i],n,edge[i+1]);
        if(mark[edge[i]]==2) mark[edge[i]] = 1;
        if(mark[edge[i+1]]==2) mark[edge[i+1]] = 1;
    }

}

int main(void)
{
    int e = 0;
    int n,m;
    scanf("%d %d",&n,&m);
    for(int i=0;i<m;i++)
    {
        int u,v;
        scanf("%d%d",&u,&v);
        nxt[e] = first[u], vv[e] = v; first[u] = e++;
        nxt[e] = first[v], vv[e] = u; first[v] = e++;
    }
    if(m&1)//m is odd
        printf("No solution\n");
    else
        dfs(1,0);
    return 0;
}


#include <iostream>
#include <algorithm>
#include <cstdio>
using namespace std;
#define maxn 10000+10
int edge[maxn],first[maxn],nxt[maxn/2];
bool v[maxn];
int mark[maxn],vv[maxn/2];

void dfs(int n,int fa)
{
    for(int e=first[n];e;e=nxt[e]) if(vv[e]!=fa && !v[vv[e]])
        dfs(vv[e],n);
    int top = 0;
    for(int e=first[n];e;e=nxt[e]) if(vv[e]!=fa && mark[vv[e]]!=1)
        edge[top++] = vv[e];

    if(top&&1)//top is odd
        edge[top++]=fa,mark[n]=1;
    else
        mark[n]=2;
    for(int i=0;i<top;i+=2)
    {
        printf("%d %d %d\n",edge[i],n,edge[i+1]);
        if(mark[edge[i]]==2) mark[edge[i]] = 1;
        if(mark[edge[i+1]]==2) mark[edge[i+1]] = 1;
    }

}

int main(void)
{
    int e = 0;
    int n,m;
    scanf("%d %d",&n,&m);
    for(int i=0;i<m;i++)
    {
        int u,v;
        scanf("%d%d",&u,&v);
        nxt[e] = first[u], vv[e] = v; first[u] = e++;
        nxt[e] = first[v], vv[e] = u; first[v] = e++;
    }
    if(m&1)//m is odd
        printf("No solution\n");
    else
        dfs(1,0);
    return 0;
}


#include <iostream>
#include <algorithm>
#include <cstdio>
using namespace std;
#define maxn 10000+10
int edge[maxn],first[maxn],nxt[maxn];
bool v[maxn];
int mark[maxn],vv[maxn];

void dfs(int n,int fa)
{
    for(int e=first[n];e;e=nxt[e]) if(vv[e]!=fa && !v[vv[e]])
        dfs(vv[e],n);
    int top = 0;
    for(int e=first[n];e;e=nxt[e]) if(vv[e]!=fa && mark[vv[e]]!=1)
        edge[top++] = vv[e];

    if(top&&1)//top is odd
        edge[top++]=fa,mark[n]=1;
    else
        mark[n]=2;
    for(int i=0;i<top;i+=2)
    {
        printf("%d %d %d\n",edge[i],n,edge[i+1]);
        if(mark[edge[i]]==2) mark[edge[i]] = 1;
        if(mark[edge[i+1]]==2) mark[edge[i+1]] = 1;
    }

}

int main(void)
{
    int e = 0;
    int n,m;
    scanf("%d %d",&n,&m);
    for(int i=0;i<m;i++)
    {
        int u,v;
        scanf("%d%d",&u,&v);
        nxt[e] = first[u], vv[e] = v; first[u] = e++;
        nxt[e] = first[v], vv[e] = u; first[v] = e++;
    }
    if(m&1)//m is odd
        printf("No solution\n");
    else
        dfs(1,0);
    return 0;
}


#include <iostream>
#include <algorithm>
#include <cstdio>
using namespace std;
#define maxn 100000+10
int edge[maxn],first[maxn],nxt[maxn];
bool v[maxn];
int mark[maxn],vv[maxn];

void dfs(int n,int fa)
{
    v[n] = 1;
    for(int e=first[n];e;e=nxt[e]) if(vv[e]!=fa && !v[vv[e]])
        dfs(vv[e],n);
    int top = 0;
    for(int e=first[n];e;e=nxt[e]) if(vv[e]!=fa && mark[vv[e]]!=1)
        edge[top++] = vv[e];

    if(top&1)//top is odd
        edge[top++]=fa,mark[n]=1;
    else
        mark[n]=2;
    for(int i=0;i<top;i+=2)
    {
        printf("%d %d %d\n",edge[i],n,edge[i+1]);
        if(mark[edge[i]]==2) mark[edge[i]] = 1;
        if(mark[edge[i+1]]==2) mark[edge[i+1]] = 1;
    }

}

int main(void)
{
    int e = 0;
    int n,m;
    scanf("%d %d",&n,&m);
    for(int i=0;i<m;i++)
    {
        int u,v;
        scanf("%d%d",&u,&v);
        nxt[e] = first[u], vv[e] = v; first[u] = e++;
        nxt[e] = first[v], vv[e] = u; first[v] = e++;
    }
    if(m&1)//m is odd
        printf("No solution\n");
    else
        dfs(1,0);
    return 0;
}


#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
using namespace std;
#define maxn 100000+10
int edge[maxn],first[maxn],nxt[maxn<<1];
bool v[maxn];
int mark[maxn],vv[maxn<<1];

void dfs(int n,int fa)
{
    v[n] = 1;
    for(int e=first[n];e!=-1;e=nxt[e]) if(vv[e]!=fa && !v[vv[e]])
        dfs(vv[e],n);
    int top = 0;
    for(int e=first[n];e!=-1;e=nxt[e]) if(vv[e]!=fa && mark[vv[e]]!=1)
        edge[top++] = vv[e];

    if(top&1)//top is odd
        edge[top++]=fa,mark[n]=1;
    else
        mark[n]=2;
    for(int i=0;i<top;i+=2)
    {
        printf("%d %d %d\n",edge[i],n,edge[i+1]);
        if(mark[edge[i]]==2) mark[edge[i]] = 1;
        if(mark[edge[i+1]]==2) mark[edge[i+1]] = 1;
    }

}

int main(void)
{
    int e = 0;
    int n,m;
    scanf("%d %d",&n,&m);
    memset(first,-1,sizeof(first));
    for(int i=0;i<m;i++)
    {
        int u,v;
        scanf("%d%d",&u,&v);
        nxt[e] = first[u], vv[e] = v; first[u] = e++;
        nxt[e] = first[v], vv[e] = u; first[v] = e++;
    }
    if(m&1)//m is odd
        printf("No solution\n");
    else
        dfs(1,0);
    return 0;
}


    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;

    const int maxn = 100010;
    int first[maxn],nxt[maxn<<1],vv[maxn<<1];
    bool vis[maxn];
    int mark[maxn];
    int edge[maxn];

    void dfs(int n,int fa)
    {
        vis[n] = true;

        for(int e=first[n];e;e=nxt[e]) if(vv[e]!=fa && !vis[vv[e]])
            dfs(vv[e], n);

        int top=0;
        for(int e=first[n];e;e=nxt[e]) if(vv[e]!=fa && mark[vv[e]]!=1)
            edge[top++]=vv[e];  // 记录可用点

        if(top&1)
            edge[top++]=fa,mark[n]=1;  // 用到当前点到父亲的边，当前点以后不可用
        else
            mark[n]=2;  // 不用到父亲的边，当前点还可以使用一次

        for(int i=0; i<top; i+=2)
        {
            printf("%d %d %d\n", edge[i], n, edge[i+1]);
            if(mark[edge[i]]==2) mark[edge[i]]=1;
            if(mark[edge[i+1]]==2) mark[edge[i+1]]=1;
        }
    }

    int main()
    {
        int e=1;
        int n,m;
        scanf("%d%d",&n,&m);
        for(int i=0;i<m;i++)
        {
            int u,v;
            scanf("%d%d",&u,&v);
            nxt[e]=first[u],vv[e]=v,first[u]=e++;
            nxt[e]=first[v],vv[e]=u,first[v]=e++;
        }

        if(m&1)
            puts("No solution");
        else
            dfs(1,0);
    }


#include <iostream>
#include <algorithm>
#include <cstdio>
using namespace std;
#define maxn 100000+10
int edge[maxn],first[maxn],nxt[maxn];
bool v[maxn];
int mark[maxn],vv[maxn];

void dfs(int n,int fa)
{
    v[n] = 1;
    for(int e=first[n];e;e=nxt[e]) if(vv[e]!=fa && !v[vv[e]])
        dfs(vv[e],n);
    int top = 0;
    for(int e=first[n];e;e=nxt[e]) if(vv[e]!=fa && mark[vv[e]]!=1)
        edge[top++] = vv[e];

    if(top&1)//top is odd
        edge[top++]=fa,mark[n]=1;
    else
        mark[n]=2;
    for(int i=0;i<top;i+=2)
    {
        printf("%d %d %d\n",edge[i],n,edge[i+1]);
        if(mark[edge[i]]==2) mark[edge[i]] = 1;
        if(mark[edge[i+1]]==2) mark[edge[i+1]] = 1;
    }

}

int main(void)
{
    int e = 1;
    int n,m;
    scanf("%d %d",&n,&m);
    for(int i=0;i<m;i++)
    {
        int u,v;
        scanf("%d%d",&u,&v);
        nxt[e] = first[u], vv[e] = v; first[u] = e++;
        nxt[e] = first[v], vv[e] = u; first[v] = e++;
    }
    if(m&1)//m is odd
        printf("No solution\n");
    else
        dfs(1,0);
    return 0;
}


#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
using namespace std;
#define maxn 100000+10
int edge[maxn],first[maxn],nxt[maxn<<1];
bool v[maxn];
int mark[maxn],vv[maxn<<1];

void dfs(int n,int fa)
{
    v[n] = 1;
    for(int e=first[n];e;e=nxt[e]) if(vv[e]!=fa && !v[vv[e]])
        dfs(vv[e],n);
    int top = 0;
    for(int e=first[n];e;e=nxt[e]) if(vv[e]!=fa && mark[vv[e]]!=1)
        edge[top++] = vv[e];

    if(top&1)//top is odd
        edge[top++]=fa,mark[n]=1;
    else
        mark[n]=2;
    for(int i=0;i<top;i+=2)
    {
        printf("%d %d %d\n",edge[i],n,edge[i+1]);
        if(mark[edge[i]]==2) mark[edge[i]] = 1;
        if(mark[edge[i+1]]==2) mark[edge[i+1]] = 1;
    }

}

int main(void)
{
    int e = 0;
    int n,m;
    scanf("%d %d",&n,&m);
    memset(first,-1,sizeof(first));
    for(int i=0;i<m;i++)
    {
        int u,v;
        scanf("%d%d",&u,&v);
        nxt[e] = first[u], vv[e] = v; first[u] = e++;
        nxt[e] = first[v], vv[e] = u; first[v] = e++;
    }
    if(m&1)//m is odd
        printf("No solution\n");
    else
        dfs(1,0);
    return 0;
}


#include <iostream>
#include <algorithm>
#include <cstdio>
using namespace std;
#define maxn 100000+10
int edge[maxn],first[maxn],nxt[maxn<<1];
bool v[maxn];
int mark[maxn],vv[maxn<<1];

void dfs(int n,int fa)
{
    v[n] = 1;
    for(int e=first[n];e;e=nxt[e]) if(vv[e]!=fa && !v[vv[e]])
        dfs(vv[e],n);
    int top = 0;
    for(int e=first[n];e;e=nxt[e]) if(vv[e]!=fa && mark[vv[e]]!=1)
        edge[top++] = vv[e];

    if(top&1)//top is odd
        edge[top++]=fa,mark[n]=1;
    else
        mark[n]=2;
    for(int i=0;i<top;i+=2)
    {
        printf("%d %d %d\n",edge[i],n,edge[i+1]);
        if(mark[edge[i]]==2) mark[edge[i]] = 1;
        if(mark[edge[i+1]]==2) mark[edge[i+1]] = 1;
    }

}

int main(void)
{
    int e = 1;
    int n,m;
    scanf("%d %d",&n,&m);
    for(int i=0;i<m;i++)
    {
        int u,v;
        scanf("%d%d",&u,&v);
        nxt[e] = first[u], vv[e] = v; first[u] = e++;
        nxt[e] = first[v], vv[e] = u; first[v] = e++;
    }
    if(m&1)//m is odd
        printf("No solution\n");
    else
        dfs(1,0);
    return 0;
}


#include<bits/stdc++.h>

using namespace std;

const int maxN = 1e5+100;

#define pb push_back
#define mp make_pair

bool mark[maxN];

vector <pair<int,int> >adj[maxN];
int n,m;

int decompose(int v)
{
	queue <int> q;

	while(q.size())
		q.pop();

	for(int i = 0; i < adj[v].size(); i++)
	{
		int e = adj[v][i].second;

		if(!mark[e])
		{
			q.push(adj[v][i].first);
			mark[e] = true;
		}
	}
	int t = q.size();
	for (int i = 0; i < t; i++)
	{
		int nei = q.front();
		int dc = decompose(nei);
		if(dc == -1)
			q.push(nei);
		else
			cout << v << " " << nei << " " << dc << endl;
		q.pop();
	}

	t = q.size();
	for(int i = 0; i < t - 1; i += 2)
	{
		cout << q.front() << " " << v << " ";
		q.pop();
		cout << q.front() << endl;
		q.pop();
	}

	if(t % 2 == 0)
		return -1;

	return q.back();
}

void input()
{

	cin>>n>>m;

	for(int i = 0,u,v; i < m; i++)
	{
		cin >> u >> v;
		adj[u].pb(mp(v,i));
		adj[v].pb(mp(u,i));
	}

}
int main()
{

	if(m & 1)
	{
		cout << "No solution" << endl;
		return 0;
	}

	decompose(1);

	return 0;
}


#include<bits/stdc++.h>

using namespace std;

const int maxN = 1e5+100;

#define pb push_back
#define mp make_pair

bool mark[maxN];

vector <pair<int,int> >adj[maxN];
int n,m;

int decompose(int v)
{
	queue <int> q;

	while(q.size())
		q.pop();

	for(int i = 0; i < adj[v].size(); i++)
	{
		int e = adj[v][i].second;

		if(!mark[e])
		{
			q.push(adj[v][i].first);
			mark[e] = true;
		}
	}
	int t = q.size();
	for (int i = 0; i < t; i++)
	{
		int nei = q.front();
		int dc = decompose(nei);
		if(dc == -1)
			q.push(nei);
		else
			cout << v << " " << nei << " " << dc << endl;
		q.pop();
	}
	t = q.size();
	for(int i = 0; i < t - 1; i += 2)
	{
		cout << q.front() << " " << v << " ";
		q.pop();
		cout << q.front() << endl;
		q.pop();
	}

	if(t % 2 == 0)
		return -1;

	return q.back();
}

void input()
{

	cin>>n>>m;

	for(int i = 0,u,v; i < m; i++)
	{
		cin >> u >> v;
		adj[u].pb(mp(v,i));
		adj[v].pb(mp(u,i));
	}

}
int main()
{
  input();
	if(m & 1)
	{
		cout << "No solution" << endl;
		return 0;
	}
	decompose(1);
	return 0;
}


#include <iostream>   //我是沙茶....今天又写搓了。。
#include <fstream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#include <stack>
#include <climits>
#include <ctime>
#include <cmath>
#include <set>
#include <map>
#include <string>
#include <vector>
#include <list>
#include <utility>
#define MAX(a,b) ((a)>(b)?(a):(b))
#define MIN(a,b) ((a)<(b)?(a):(b))
#define abs(x) ((x)>0?(x):(-(x)))
#define FOR(i,a,b) for(int i = (a);i<=(b);i++)
#define FORD(i,a,b) for(int i = (a);i>=(b);i--)
#define REP(i,n) for(int i = 0;i<(n);i++)
#define rst(x,k) memset(x,k,sizeof(x))
#define lowbit(x) ((x)&(-(x)))
#define h(x) (1<<(x))
#define lson (ind<<1)
#define rson (ind<<1|1)
#define eps 1e-8
#define INF 50000000
#define maxn 110000
#define mod 1000000007LL
#define Pi acos(-1.0)
#define link fjksldfjaslkdfjas
using namespace std;
typedef long long LL;
struct node{
    int t,nxt;
    bool block;
}edge[maxn];
int headline[maxn] , E;
inline void add(int f,int t){
    edge[E].t = t;
    edge[E].nxt = headline[f];
    edge[E].block = false;
    headline[f] = E++;
}
int n,m;
int dfs(int u){
    vector<int> adj;
    for(int i = headline[u];~i;i = edge[i].nxt){
        if(edge[i].block)continue;
        edge[i].block = edge[i ^ 1].block = true;
        adj.push_back(edge[i].t);
    }
    int ss = adj.size();
    queue<int> q;
    for(int i = 0;i<ss;i++){
        int ww = dfs(adj[i]);
        if(ww == 0){
            q.push(adj[i]);
        }else{
            printf("%d %d %d\n",u,adj[i],ww);
        }
    }
    int x = -1 , y = -1;
    while(!q.empty()){
        if(x == -1){
            x = q.front(); q.pop();
        }else{
            y = q.front(); q.pop();
            printf("%d %d %d\n",x,u,y);
            x = y = -1;
        }
    }
    if(x == -1)return 0;
    return x;
}
void solve(void){
    rst(headline,-1); E = 0;
    REP(i,m){
        int a,b; scanf("%d%d",&a,&b);
        add(a,b); add(b,a);
    }
    if(m % 2){
        printf("No solution\n");
        return;
    }
    dfs(1);
}
int main(void){
    while(2 == scanf("%d%d",&n,&m)) solve();
}


#include <iostream>   //我是沙茶....今天又写搓了。。
#include <fstream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#include <stack>
#include <climits>
#include <ctime>
#include <cmath>
#include <set>
#include <map>
#include <string>
#include <vector>
#include <list>
#include <utility>
#define MAX(a,b) ((a)>(b)?(a):(b))
#define MIN(a,b) ((a)<(b)?(a):(b))
#define abs(x) ((x)>0?(x):(-(x)))
#define FOR(i,a,b) for(int i = (a);i<=(b);i++)
#define FORD(i,a,b) for(int i = (a);i>=(b);i--)
#define REP(i,n) for(int i = 0;i<(n);i++)
#define rst(x,k) memset(x,k,sizeof(x))
#define lowbit(x) ((x)&(-(x)))
#define h(x) (1<<(x))
#define lson (ind<<1)
#define rson (ind<<1|1)
#define eps 1e-8
#define INF 50000000
#define maxn 110000
#define mod 1000000007LL
#define Pi acos(-1.0)
#define link fjksldfjaslkdfjas
using namespace std;
typedef long long LL;
struct node{
    int t,nxt;
    bool block;
}edge[maxn<<1];
int headline[maxn] , E;
inline void add(int f,int t){
    edge[E].t = t;
    edge[E].nxt = headline[f];
    edge[E].block = false;
    headline[f] = E++;
}
int n,m;
int dfs(int u){
    vector<int> adj;
    for(int i = headline[u];~i;i = edge[i].nxt){
        if(edge[i].block)continue;
        edge[i].block = edge[i ^ 1].block = true;
        adj.push_back(edge[i].t);
    }
    int ss = adj.size();
    queue<int> q;
    for(int i = 0;i<ss;i++){
        int ww = dfs(adj[i]);
        if(ww == 0){
            q.push(adj[i]);
        }else{
            printf("%d %d %d\n",u,adj[i],ww);
        }
    }
    int x = -1 , y = -1;
    while(!q.empty()){
        if(x == -1){
            x = q.front(); q.pop();
        }else{
            y = q.front(); q.pop();
            printf("%d %d %d\n",x,u,y);
            x = y = -1;
        }
    }
    if(x == -1)return 0;
    return x;
}
void solve(void){
    rst(headline,-1); E = 0;
    REP(i,m){
        int a,b; scanf("%d%d",&a,&b);
        add(a,b); add(b,a);
    }
    if(m % 2){
        printf("No solution\n");
        return;
    }
    dfs(1);
}
int main(void){
    while(2 == scanf("%d%d",&n,&m)) solve();
}


#include <cstdio>

#define N 100000

bool a[N * 2 + 1], aa[N + 1];
int b[N * 2 + 1], c[N * 2 + 1], h[N + 1], n, m, i, x, y;

int go(int k)
{
	aa[k] = 1;
	int i, t, x = 0;
	for (i = h[k]; i; i = b[i])
		if (!a[i])
		{
			a[i > m ? i - m : i + m] = 1;
			if (t = aa[c[i]] ? 0 : go(c[i]))
				printf("%d %d %d\n", k, c[i], t);
			else
				if (x)
					printf("%d %d %d\n", x, k, c[i]), x = 0;
				else
					x = c[i];
		}

	return x;
}

int main()
{
	scanf("%d%d", &n, &m);

	if (m & 1)
	{
		puts("No solution");
		return 0;
	}

	for (i = 1; i <= m; ++i)
	{
		scanf("%d%d", &x, &y);
		b[i] = h[x];
		c[i] = y;
		h[x] = i;
		b[i + m] = h[y];
		c[i + m] = x;
		h[y] = i + m;
	}

	go(1);

	return 0;
}


#include <cstdio>

#define N 100000

bool a[N * 2 + 1], aa[N + 1];
int b[N * 2 + 1], c[N * 2 + 1], h[N + 1], n, m, i, x, y;

int go(int k)
{
	aa[k] = 1;
	int i, t, x = 0;
	for (i = h[k]; i; i = b[i])
		if (!a[i])
		{
			a[i >= m ? i - m : i + m] = 1;
			if (t = aa[c[i]] ? 0 : go(c[i]))
				printf("%d %d %d\n", k, c[i], t);
			else
				if (x)
					printf("%d %d %d\n", x, k, c[i]), x = 0;
				else
					x = c[i];
		}

	return x;
}

int main()
{
	scanf("%d%d", &n, &m);

	if (m & 1)
	{
		puts("No solution");
		return 0;
	}

	for (i = 0; i < m; ++i)
	{
		scanf("%d%d", &x, &y);
		b[i] = h[x];
		c[i] = y;
		h[x] = i;
		b[i + m] = h[y];
		c[i + m] = x;
		h[y] = i + m;
	}

	go(1);

	return 0;
}


#include<bits/stdc++.h>
using namespace std;
const int maxn=100005;
int cnt=0,visit[maxn];
struct ANS{int a,b,c;}ans[maxn];
vector<int>V[maxn];
int dfs(int u,int pre)
{
    int i;
    visit[u]=visit[pre]+1;
    vector<int>ADD;
    for(i=0;i<V[u].size();i++){
        int v=V[u][i];
        if(visit[v])  {if(visit[u]<visit[v])  ADD.push_back(v);continue;}
        int temp=dfs(v,u);
        if(temp)
            ans[cnt++]=(ANS){u,v,temp};
        else
            ADD.push_back(v);
    }
    //printf("ADD[%d].size  %d\n",u,ADD.size());
    //if(u==3){
        //printf("ooops\n");
        //for(i=0;i<ADD.size();i++)
            //printf("%d ",ADD[i]);
        //printf("\n");
    //}
    for(i=0;i<(int)ADD.size()-1;i+=2)
        ans[cnt++]=(ANS){ADD[i],u,ADD[i+1]};
    if(i==ADD.size()-1)  return ADD[ADD.size()-1];
    return 0;
}
int main()
{
    //freopen("405E.txt","r",stdin);
    int n,m,i;
    memset(V,0,sizeof(V));
    memset(visit,0,sizeof(visit));
    scanf("%d %d",&n,&m);
    while(m--){
        int u,v;
        scanf("%d %d",&u,&v);
        V[u].push_back(v);
        V[v].push_back(u);
    }
    int temp=dfs(1,0);
    //for(i=1;i<=n;i++)
        //printf("%d %d\n",i,visit[i]);
    if(temp)  printf("No solution\n");
    else{
        for(i=0;i<cnt;i++)
            printf("%d %d %d\n",ans[i].a,ans[i].b,ans[i].c);
    }
    return 0;
}


#include<bits/stdc++.h>
using namespace std;
const int maxn=1005;
int cnt=0,visit[maxn];
struct ANS{int a,b,c;}ans[maxn];
vector<int>V[maxn];
int dfs(int u,int pre)
{
    int i;
    visit[u]=visit[pre]+1;
    vector<int>ADD;
    for(i=0;i<V[u].size();i++){
        int v=V[u][i];
        if(visit[v])  {if(visit[u]<visit[v])  ADD.push_back(v);continue;}
        int temp=dfs(v,u);
        if(temp)
            ans[cnt++]=(ANS){u,v,temp};
        else
            ADD.push_back(v);
    }
    //printf("ADD[%d].size  %d\n",u,ADD.size());
    //if(u==3){
        //printf("ooops\n");
        //for(i=0;i<ADD.size();i++)
            //printf("%d ",ADD[i]);
        //printf("\n");
    //}
    for(i=0;i<(int)ADD.size()-1;i+=2)
        ans[cnt++]=(ANS){ADD[i],u,ADD[i+1]};
    if(i==ADD.size()-1)  return ADD[ADD.size()-1];
    return 0;
}
int main()
{
    //freopen("405E.txt","r",stdin);
    int n,m,i;
    memset(V,0,sizeof(V));
    memset(visit,0,sizeof(visit));
    scanf("%d %d",&n,&m);
    while(m--){
        int u,v;
        scanf("%d %d",&u,&v);
        V[u].push_back(v);
        V[v].push_back(u);
    }
    int temp=dfs(1,0);
    //for(i=1;i<=n;i++)
        //printf("%d %d\n",i,visit[i]);
    if(temp)  printf("No solution\n");
    else{
        for(i=0;i<cnt;i++)
            printf("%d %d %d\n",ans[i].a,ans[i].b,ans[i].c);
    }
    return 0;
}


#include<bits/stdc++.h>
using namespace std;
const int maxn=100005;
int cnt=0,visit[maxn];
struct ANS{int a,b,c;}ans[maxn];
vector<int>V[maxn];
int dfs(int u,int pre)
{
    int i;
    visit[u]=visit[pre]+1;
    vector<int>ADD;
    for(i=0;i<V[u].size();i++){
        int v=V[u][i];
        if(visit[v])  {if(visit[u]<visit[v])  ADD.push_back(v);continue;}
        int temp=dfs(v,u);
        if(temp)
            ans[cnt++]=(ANS){u,v,temp};
        else
            ADD.push_back(v);
    }
    for(i=0;i<(int)ADD.size()-1;i+=2)
        ans[cnt++]=(ANS){ADD[i],u,ADD[i+1]};
    if(i==ADD.size()-1)  return ADD[ADD.size()-1];
    return 0;
}
int main()
{
    //freopen("405E.txt","r",stdin);
    int n,m,i;
    memset(V,0,sizeof(V));
    memset(visit,0,sizeof(visit));
    scanf("%d %d",&n,&m);
    while(m--){
        int u,v;
        scanf("%d %d",&u,&v);
        V[u].push_back(v);
        V[v].push_back(u);
    }
    int temp=dfs(1,0);
    if(temp)  printf("No solution\n");
    else{
        for(i=0;i<cnt;i++)
            printf("%d %d %d\n",ans[i].a,ans[i].b,ans[i].c);
    }
    return 0;
}


#include <iostream>
#include <queue>
#include <vector>

using namespace std;

const int maxn = 100 * 1000 + 5;

#define pb push_back
#define mp make_pair

bool Mark[maxn];

vector < pair <int,int> > adj[maxn];

int decompose(int v)
{
	queue <int> q;

	while(q.size())
		q.pop();

	for(int i = 0; i < adj[v].size(); i++)
	{
		int e = adj[v][i].second;

		if(!Mark[e])
		{
			q.push(adj[v][i].first);
			Mark[e] = true;
		}
	}
	int t = q.size();
	for (int i = 0; i < t; i++)
	{
		int nei = q.front();
		int dc = decompose(nei);
		if(dc == -1)
			q.push(nei);
		else
			cout << v << " " << nei << " " << dc << endl;
		q.pop();
	}

	t = q.size();
	for(int i = 0; i < t - 1; i += 2)
	{
		cout << q.front() << " " << v << " ";
		q.pop();
		cout << q.front() << endl;
		q.pop();
	}

	if(t % 2 == 0)
		return -1;

	return q.back();
}

int main()
{
	int n,m;
	cin >> n >> m;

	for(int i = 0,u,v; i < m; i++)
	{
		cin >> u >> v;
		adj[u].pb(mp(v,i));
		adj[v].pb(mp(u,i));
	}

	if(m & 1)
	{
		cout << "No solution" << endl;
		return 0;
	}

	decompose(1);

	return 0;
}


//UESTC_L3

#include <stdexcept>
#include <cstdarg>
#include <iostream>
#include <fstream>
#include <exception>
#include <memory>
#include <locale>
#include <sstream>
#include <set>
#include <list>
#include <bitset>
#include <fstream>
#include <numeric>
#include <iomanip>
#include <string>
#include <utility>
#include <cctype>
#include <climits>
#include <cassert>
#include <cstdio>
#include <cstring>
#include <map>
#include <cmath>
#include <algorithm>
#include <ctime>
#include <vector>
#include <queue>
#include <deque>
#include <cstdlib>
#include <stack>
#include <iterator>
#include <functional>
#include <complex>
#include <valarray>
using namespace std;

const int N=210000;

struct Edge
{
    int next,to;
    Edge(int to=0,int next=-1):to(to),next(next){
    }
};
int head[N],countedge;
Edge edge[N];

void AddEdge(const int& s,const int& t)
{
    edge[countedge]=Edge(t,head[s]);
    head[s]=countedge++;
}

void init()
{
    memset(head,-1,sizeof(head));
    countedge=0;
}

bool vis[N];
vector<int> unpair[N];

int dfs(int u)
{
    int temp;
    for(temp=head[u];temp!=-1;temp=edge[temp].next)
    {
        int v=edge[temp].to;
        if(vis[temp])continue;
        vis[temp]=true;
        vis[temp^1]=true;

        int w=dfs(v);
        if(w)
        {
            printf("%d %d %d\n",u,v,w);
        }
        else unpair[u].push_back(v);
    }

    int len=unpair[u].size();
    while(len>=2)
    {
        printf("%d %d %d\n",unpair[u][len-1],u,unpair[u][len-2]);
        len-=2;
    }
    if(len)return unpair[u][0];
    return 0;
}

int main()
{
    int n,m;
    scanf("%d%d",&n,&m);

    init();
    for(int i=0;i<m;i++)
    {
        int u,v;
        scanf("%d%d",&u,&v);
        AddEdge(u,v);
        AddEdge(v,u);
    }

    if(m&1)
    {
        printf("No solution\n");
        return 0;
    }
    else dfs(1);

    return 0;
}


//UESTC_L3

#include <stdexcept>
#include <cstdarg>
#include <iostream>
#include <fstream>
#include <exception>
#include <memory>
#include <locale>
#include <sstream>
#include <set>
#include <list>
#include <bitset>
#include <fstream>
#include <numeric>
#include <iomanip>
#include <string>
#include <utility>
#include <cctype>
#include <climits>
#include <cassert>
#include <cstdio>
#include <cstring>
#include <map>
#include <cmath>
#include <algorithm>
#include <ctime>
#include <vector>
#include <queue>
#include <deque>
#include <cstdlib>
#include <stack>
#include <iterator>
#include <functional>
#include <complex>
#include <valarray>
using namespace std;

const int N=210000;

struct Edge
{
    int next,to;
    Edge(int to=0,int next=-1):to(to),next(next){
    }
};
int head[N],countedge;
Edge edge[N];

void AddEdge(const int& s,const int& t)
{
    edge[countedge]=Edge(t,head[s]);
    head[s]=countedge++;
}

void init()
{
    memset(head,-1,sizeof(head));
    countedge=0;
}

bool vis[N];

int dfs(int u)
{
    int temp;
    queue<int> que;
    vector<int> unpair;
    for(temp=head[u];temp!=-1;temp=edge[temp].next)
    {
        int v=edge[temp].to;
        if(vis[temp])continue;
        vis[temp]=true;
        vis[temp^1]=true;
        que.push(v);
    }

    while(!que.empty())
    {
        int v=que.front();
        que.pop();
        int w=dfs(v);
        if(w)printf("%d %d %d\n",u,v,w);
        else unpair.push_back(v);
    }

    int len=unpair.size();
    while(len>=2)
    {
        printf("%d %d %d\n",unpair[len-1],u,unpair[len-2]);
        len-=2;
    }
    if(len)return unpair[0];
    return 0;
}

int main()
{
    int n,m;
    scanf("%d%d",&n,&m);

    init();
    for(int i=0;i<m;i++)
    {
        int u,v;
        scanf("%d%d",&u,&v);
        AddEdge(u,v);
        AddEdge(v,u);
    }

    if(m&1)
    {
        printf("No solution\n");
        return 0;
    }
    else dfs(1);

    return 0;
}


#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <stdio.h>
using namespace std;
class sp{
  public:
  int q;
  sp *w;
  sp(int q1,sp *w1){
   q=q1;w=w1;}
};
sp *a[100001];
int y,s[100001],f[100000],h[50000],h1[50000],h2[50000];
bool l(int q,int w){
  int e=-1;
  sp *c;
  for(c=a[q];c;c=c->w)
   if(c->q!=w)
    if(l(c->q,q))
     if(e<0)
      e=s[c->q];
     else{
      h[y]=e;
      h1[y]=q;
      h2[y]=s[c->q];
      y++;
      e=-1;}
  if(e>=0){
   h[y]=e;
   h1[y]=q;
   h2[y]=w;
   y++;
   return 0;}
  return 1;
}
int k(int q){
  if(f[f[q]]!=f[q])
   f[q]=k(f[q]);
  return f[q];
}
int main(){
  //freopen("input.txt","r",stdin);
  //freopen("output.txt","w",stdout);
  int q,w,e,r;
  scanf("%d%d",&q,&w);
  if(w%2==1){
   printf("No solution");
   return 0;}
  for(e=0;e<q;e++){
   a[e]=0;
   s[e]=f[e]=e;}
  y=q;
  for(;w;w--){
   scanf("%d%d",&e,&r);
   e--;r--;
   if(k(e)!=k(r)){
    f[k(e)]=k(r);
    a[e]=new sp(r,a[e]);
    a[r]=new sp(e,a[r]);}
   else{
    a[y]=0;
    s[y]=r;
    a[e]=new sp(y,a[e]);
    y++;}}
  y=0;
  e=l(0,0);
  for(w=0;w<y;w++)
   printf("%d %d %d\n",h[w]+1,h1[w]+1,h2[w]+1);
  return 0;}


#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <stdio.h>
using namespace std;
class sp{
  public:
  int q;
  sp *w;
  sp(int q1,sp *w1){
   q=q1;w=w1;}
};
sp *a[100001];
int y,s[100001],f[100000],h[50000],h1[50000],h2[50000];
bool l(int q,int w){
  int e=-1;
  sp *c;
  for(c=a[q];c;c=c->w)
   if(c->q!=w)
    if(l(c->q,q))
     if(e<0)
      e=s[c->q];
     else{
      h[y]=e;
      h1[y]=q;
      h2[y]=c->q;
      y++;
      e=-1;}
  if(e>=0){
   h[y]=e;
   h1[y]=q;
   h2[y]=w;
   y++;
   return 0;}
  return 1;
}
int k(int q){
  if(f[f[q]]!=f[q])
   f[q]=k(f[q]);
  return f[q];
}
int main(){
  //freopen("input.txt","r",stdin);
  //freopen("output.txt","w",stdout);
  int q,w,e,r;
  scanf("%d%d",&q,&w);
  if(w%2==1){
   printf("No solution");
   return 0;}
  for(e=0;e<q;e++){
   a[e]=0;
   s[e]=f[e]=e;}
  y=q;
  for(;w;w--){
   scanf("%d%d",&e,&r);
   e--;r--;
   if(k(e)!=k(r)){
    f[k(e)]=k(r);
    a[e]=new sp(r,a[e]);
    a[r]=new sp(e,a[r]);}
   else{
    a[y]=0;
    s[y]=r;
    a[e]=new sp(y,a[e]);
    y++;}}
  y=0;
  e=l(0,0);
  for(w=0;w<y;w++)
   printf("%d %d %d\n",h[w]+1,h1[w]+1,h2[w]+1);
  return 0;}


#include<iostream>
#include<vector>
#include<stdio.h>
#define pb push_back
using namespace std;
vector<int>g[100005],s[100005],A,B,C;
int i,j,k,t,l,m,n,w,f[100005],V[10005];

int go (int v)
{
     vector < int > V;
     for (int i=0;i<g[v].size();i++)
     if (!f[s[v][i]])
     {
        f[s[v][i]]=1;
        w=go(g[v][i]);
        if (w)
        {
              A.pb(v);
              B.pb(g[v][i]);
              C.pb(w);
        } else V.pb(g[v][i]);
}

     for (int i=1;i<V.size();i+=2)A.pb(V[i]),B.pb(v),C.pb(V[i-1]);

     if (V.size()%2) return V.back();

     return 0;
}
main()
{
     scanf("%d%d",&n,&m);
     for (i=1;i<=m;i++)
     {
                       int x,y;
       scanf("%d%d",&x,&y);
       g[x].pb(y);
       g[y].pb(x);
       s[x].pb(i);
       s[y].pb(i);
     }
  for (i=1;i<=n;i++)if (go(i)){cout<<"No solution"<<endl;return 0;}

  for (i=0;i<A.size();i++)printf("%d %d %d\n",A[i],B[i],C[i]);
}


#include <cstdio>
#include <algorithm>
#include <vector>
#include <vector>
using namespace std;

const int MAX_N=100100;

vector<int> A[MAX_N];
bool viz[MAX_N];
int h[MAX_N];

int dfs(int nod,int dad) {
    viz[nod]=true;
    h[nod]=h[dad]+1;
    int e=0;
    for(auto it=A[nod].begin(); it!=A[nod].end(); it++) {
        if(!viz[*it]) {
            e+=1+dfs(*it,nod);
        }
        else if(h[*it]<h[nod]&&*it!=dad) {
            e++;
        }
    }

    while(e>=2) {
        while(A[nod].back()==dad||h[A[nod].back()]>h[nod]+1) {
            A[nod].pop_back();
        }
        int nod1=A[nod].back();
        A[nod].pop_back();

        while(A[nod].back()==dad||h[A[nod].back()]>h[nod]+1) {
            A[nod].pop_back();
        }
        int nod2=A[nod].back();
        A[nod].pop_back();
        printf("%d %d %d\n",nod1,nod,nod2);
        e-=2;
    }

    if(e==1) {
        while(A[nod].back()==dad||h[A[nod].back()]>h[nod]+1) {
            A[nod].pop_back();
        }
        int nod1=A[nod].back();
        A[nod].pop_back();
        printf("%d %d %d\n",nod1,nod,dad);
        h[nod]=h[dad]+2;
        return -1;
    }

    return e;
}

int main() {
    int n,m;
    scanf("%d%d",&n,&m);
    if(m&1) {
        printf("No solution");
        return 0;
    }
    for(int i=1;i<=m;i++) {
        int a,b;
        scanf("%d%d",&a,&b);
        A[a].push_back(b);
        A[b].push_back(a);
    }
    dfs(1,0);
    return 0;
}


#include <bits/stdc++.h>
using namespace std;
#define fl(i,a,b) for(int i=a;i<b;i++)
#define ll long long
#define endl '\n'
#define pb push_back
#define ff first
#define ss second
#define mode 998244353
#define mx 200005
#define mx2 15
#define inf 1e17
#define fast ios_base::sync_with_stdio(0);cin.tie(NULL);cout.tie(NULL);
vector<int> v[mx];
bool vis[mx];
set<int> s[mx];
void dfs(int x,int p)
{
	vis[x] = 1;
	vector<int> temp;
	for(int i = 0; i < v[x].size(); i++){
		if(!vis[v[x][i]]){
			dfs(v[x][i],x);
		}
		else{
			if(s[x].find(v[x][i]) != s[x].end() && v[x][i] != p)
			temp.pb(v[x][i]);
		}
	}
	for(int i = 1; i <temp.size(); i++){
		cout<<temp[i-1]<<" "<<x<<" "<<temp[i]<<endl;
		s[temp[i-1]].erase(x);
		s[x].erase(temp[i-1]);
		s[temp[i]].erase(x);
		s[x].erase(temp[i]);
		i++;
	}
	vector<int> another;
	temp.clear();
	for(int i = 0; i < v[x].size(); i++){
		if(v[x][i] != p && s[x].find(v[x][i]) != s[x].end()){
			temp.pb(v[x][i]);
		}
	}
	for(int i = 1; i < temp.size(); i++){
		cout<<temp[i-1]<<" "<<x<<" "<<temp[i]<<endl;
		s[temp[i-1]].erase(x);
		s[x].erase(temp[i-1]);
		s[temp[i]].erase(x);
		s[x].erase(temp[i]);
		i++;
	}
	if(temp.size() & 1){
		cout<<p<<" "<<x<<" "<<temp.back()<<endl;
		s[p].erase(x);
		s[x].erase(p);
		s[temp.back()].erase(x);
		s[x].erase(temp.back());

	}

}
main()
{
	fast;
	int n, m;
	cin >> n >> m;
	if(m&1){
		return cout<<"No solution",0;
	}

	for(int i = 0; i < m; i++){
		int x,y;
		cin >> x >> y;
		v[x].pb(y);
		v[y].pb(x);
		s[x].insert(y);
		s[y].insert(x);
	}

	dfs(1,0);

}


#include <bits/stdc++.h>
using namespace std;
#define fl(i,a,b) for(int i=a;i<b;i++)
#define ll long long
#define endl '\n'
#define pb push_back
#define ff first
#define ss second
#define mode 998244353
#define mx 200005
#define mx2 15
#define inf 1e17
#define fast ios_base::sync_with_stdio(0);cin.tie(NULL);cout.tie(NULL);
vector<int> v[mx];
bool vis[mx];
set<int> s[mx];
void dfs(int x,int p)
{
	vis[x] = 1;
	vector<int> temp;
	for(int i = 0; i < v[x].size(); i++){
		if(!vis[v[x][i]]){
			dfs(v[x][i],x);
		}
		else{
			if(s[x].find(v[x][i]) != s[x].end() && v[x][i] != p)
			temp.pb(v[x][i]);
		}
	}
	for(int i = 1; i <temp.size(); i++){
		cout<<temp[i-1]<<" "<<x<<" "<<temp[i]<<endl;
		s[temp[i-1]].erase(x);
		s[x].erase(temp[i-1]);
		s[temp[i]].erase(x);
		s[x].erase(temp[i]);
		i++;
	}
	vector<int> another;
	temp.clear();
	for(int i = 0; i < v[x].size(); i++){
		if(v[x][i] != p && s[x].find(v[x][i]) != s[x].end()){
			temp.pb(v[x][i]);
		}
	}
	for(int i = 1; i < temp.size(); i++){
		cout<<temp[i-1]<<" "<<x<<" "<<temp[i]<<endl;
		s[temp[i-1]].erase(x);
		s[x].erase(temp[i-1]);
		s[temp[i]].erase(x);
		s[x].erase(temp[i]);
		i++;
	}
	if(temp.size() & 1){
		cout<<p<<" "<<x<<" "<<temp.back()<<endl;
		s[p].erase(x);
		s[x].erase(p);
		s[temp.back()].erase(x);
		s[x].erase(temp.back());

	}

}
main()
{
	fast;
	int n, m;
	cin >> n >> m;
	if(m&1){
		return cout<<"No Solution",0;
	}

	for(int i = 0; i < m; i++){
		int x,y;
		cin >> x >> y;
		v[x].pb(y);
		v[y].pb(x);
		s[x].insert(y);
		s[y].insert(x);
	}

	dfs(1,0);

}


/*mohammadreza motabar*/
#include<bits/stdc++.h>
using namespace std;
#define F first
#define S second
#define ll long long
#define pb push_back
typedef pair<int,int> pii;
typedef pair<long long int,long long int> pll;
const ll MAX_N = 1e5+10 , INF = 1e9;
int n,m,from[MAX_N],to[MAX_N],tkhor[MAX_N],tvor[MAX_N],d[MAX_N];
vector<int> adj[MAX_N],khor[MAX_N],vor[MAX_N],fard,efkhor[MAX_N];
bool vis[MAX_N],avaz[MAX_N],mar[MAX_N];
int tyal(int v){
	vis[v]=1;
	int ret=adj[v].size();
	for(int k:adj[v]){
		int u=from[k]^to[k]^v;
		if(!vis[u]){
			ret+=tyal(u);
		}
	}
	return ret;
}
void ffar(int v){
	vis[v]=1;
	if(tkhor[v]%2==1) fard.pb(v);
	for(int k:adj[v]){
		int u=from[k]^to[k]^v;
		if(!vis[u]){
			ffar(u);
		}
	}
}
void avyal(int v,int yp=0){
	mar[v]=1;
	for(int k:adj[v]){
		int u=from[k]^to[k]^v;
		if(!mar[u]){
			avyal(u,k);
			d[v]+=d[u];
		}
	}
	if(d[v]%2==1) avaz[yp]=1;
}
void hal(int v){
	fard.clear();
	ffar(v);
	memset(mar,0,sizeof mar);
	for(int i=0;i<fard.size();i++){
			d[fard[i]]++;
	}
	avyal(v);
}
int main(){
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    cin>>n>>m;
    for(int i=0;i<m;i++){
    	int a,b;
    	cin>>a>>b;
    	tkhor[a]++;
    	from[i]=a;
    	to[i]=b;
    	adj[a].pb(i);
    	adj[b].pb(i);
	}
	for(int i=1;i<=n;i++){
		if(!vis[i]){
			if((tyal(i)/2)%2==1){
				cout<<"No solution"<<endl;
				return 0;
			}
		}
	}
	memset(vis,0,sizeof vis);
	for(int i=1;i<=n;i++){
		if(!vis[i]){
			hal(i);
		}
	}
	for(int i=0;i<m;i++){
		if(avaz[i]==1){
			efkhor[to[i]].pb(from[i]);
		}
		else{
			efkhor[from[i]].pb(to[i]);
		}
	}
	for(int i=1;i<=n;i++){
		for(int j=0;j<efkhor[i].size();j+=2){
			cout<<efkhor[i][j]<<" "<<i<<" "<<efkhor[i][j+1]<<endl;
		}
	}
}


#include <bits/stdc++.h>
#define MAX_N 100000
#define MAX_M 100000
using namespace std;

int n, m;
vector<int> graph[MAX_N];
unordered_set<int> blocked[MAX_N];

vector<tuple<int, int, int>> rs;

int dfs(int u) {

    unordered_set<int> adj;
    unordered_set<int> unpaired;

    for (int v : graph[u]) {
        if (blocked[u].find(v) == blocked[u].end()) {
            adj.insert(v);
            unpaired.insert(v);
            blocked[u].insert(v);
            blocked[v].insert(u);
        }
    }

    for (int v : graph[u]) {
        if (adj.find(v) == adj.end()) continue;
        int w = dfs(v);
        if (w != -1) {
            rs.push_back(make_tuple(u, v, w));
            unpaired.erase(v);
        }
    }

    while (unpaired.size() >= 2) {
        auto ptr = unpaired.begin();
        int a = *ptr;
        unpaired.erase(ptr);
        ptr = unpaired.begin();
        int b = *ptr;
        unpaired.erase(ptr);
        rs.push_back(make_tuple(a, u, b));
    }

    if (!unpaired.empty()) {
        return *unpaired.begin();
    }

    return -1;
}

int main() {
    int u, v;
    cin >> n >> m;
    for (int i = 0; i < m; ++i) {
        cin >> u >> v;
        graph[u - 1].push_back(v - 1);
        graph[v - 1].push_back(u - 1);
    }

    int last = dfs(0);
    if (last == -1) {
        for (auto ans : rs) {
            cout << (get<0>(ans) + 1) << " " << (get<1>(ans) + 1) << " " << (get<2>(ans) + 1) << endl;
        }
    } else {
        cout << "No solution" << endl;
    }

    return 0;
}


#include <bits/stdc++.h>
using namespace std;
#define MOD 1000000007
#define PI 3.14159265358979323846
#define forn(i,s,n) for(int i=s ; i<n ; i++)
#define fornr(i,s,n) for(int i=n ; i>s ; i--)
#define mp make_pair
#define pb push_back
#define fr first
#define sc second
const int SIZE=4000000;
const int OO = (int)1e9;
typedef vector<int> vi;
typedef unsigned long long int ll;
typedef pair<int , int > ii;
typedef pair<pair<int, double> , int > iii;

bool comp(iii a , iii b){
     return a.first.first * b.first.second < a.first.second * b.first.first ;
}
map<ii, bool > mpp;
vi v[100009];
int State[100009];
const int UNVISTED = 0 , VISITED = 1 , EXPLORED = 2;
int dfs(int node){

     State[node] = EXPLORED;
     vi un;
     forn(i , 0 , v[node].size()){

          int ch = v[node][i];

              if(State[ch]==UNVISTED){
               int xx =  dfs(ch);
               if(xx==0){
                    un.pb(ch);
               }else {

                    printf("%d %d %d\n" , node , ch , xx);
               }

            }else if(State[ch]==VISITED)
              un.pb(ch);

     }
          while(un.size()>=2){
               int a = un.back();
               un.pop_back();
               int b = un.back();

               un.pop_back();
               printf("%d %d %d\n" , a , node ,b);

          }
          State[node]=VISITED;
          if(!un.size()){
               return 0;
          }else {
               int chh = un.back();
               un.pop_back();
               return chh;
          }

}
int main(){
     int n , m;
     scanf("%d %d" , &n , &m);
     if(m&1)return puts("No solution");
     forn(i , 0 , m){
          int x , y;
          scanf("%d %d" , &x , &y);
          v[x].pb(y);
          v[y].pb(x);
     }
     dfs(1);

}


#include <bits/stdc++.h>
using namespace std;
#define MOD 1000000007
#define PI 3.14159265358979323846
#define forn(i,s,n) for(int i=s ; i<n ; i++)
#define fornr(i,s,n) for(int i=n ; i>s ; i--)
#define mp make_pair
#define pb push_back
#define fr first
#define sc second
const int SIZE=4000000;
const int OO = (int)1e9;
typedef vector<int> vi;
typedef unsigned long long int ll;
typedef pair<int , int > ii;
typedef pair<pair<int, double> , int > iii;

bool comp(iii a , iii b){
     return a.first.first * b.first.second < a.first.second * b.first.first ;
}
map<ii, bool > mpp;
vi v[100009];

int dfs(int node){
     vi adj;
     forn(i , 0 , v[node].size())if(!mpp[{node , v[node][i]}])adj.pb(v[node][i]);
     vi un;
     forn(i , 0 , adj.size()){
          int ch = adj[i];

               mpp[{node , ch}]=1;
               mpp[{ch , node}]=1;
               int xx =  dfs(ch);
               if(xx==0){
                    un.pb(ch);
               }else {
                    printf("%d %d %d\n" , node , ch , xx);
               }

     }
          while(un.size()>=2){
               int a = un.back();
               un.pop_back();
               int b = un.back();

               un.pop_back();
               printf("%d %d %d\n" , a , node ,b);

          }
          if(!un.size()){
               return 0;
          }else {
               int chh = un.back();
               un.pop_back();
               return chh;
          }

}
int main(){
     int n , m;
     scanf("%d %d" , &n , &m);
     if(m&1)return puts("No solution");
     forn(i , 0 , m){
          int x , y;
          scanf("%d %d" , &x , &y);
          v[x].pb(y);
          v[y].pb(x);
     }
     dfs(1);

}


#include <bits/stdc++.h>
using namespace std;
#define MOD 1000000007
#define PI 3.14159265358979323846
#define forn(i,s,n) for(int i=s ; i<n ; i++)
#define fornr(i,s,n) for(int i=n ; i>s ; i--)
#define mp make_pair
#define pb push_back
#define fr first
#define sc second
const int SIZE=4000000;
const int OO = (int)1e9;
typedef vector<int> vi;
typedef unsigned long long int ll;
typedef pair<int , int > ii;
typedef pair<pair<int, double> , int > iii;

bool comp(iii a , iii b){
     return a.first.first * b.first.second < a.first.second * b.first.first ;
}
map<ii, bool > mpp;
vi v[100009];

int dfs(int node){
     vi un;
     forn(i , 0 , v[node].size()){
          int ch = v[node][i];
          if(!mpp[{node , ch}]){
               mpp[{node , ch}]=1;
               mpp[{ch , node}]=1;
               int xx =  dfs(ch);
               if(xx==0){
                    un.pb(ch);
               }else {
                    printf("%d %d %d\n" , node , ch , xx);
               }
          }

     }
          while(un.size()>=2){
               int a = un.back();
               un.pop_back();
               int b = un.back();

               un.pop_back();
               printf("%d %d %d\n" , a , node ,b);

          }
          if(!un.size()){
               return 0;
          }else {
               int chh = un.back();
               un.pop_back();
               return chh;
          }

}
int main(){
     int n , m;
     scanf("%d %d" , &n , &m);
     if(m&1)return puts("No solution");
     forn(i , 0 , m){
          int x , y;
          scanf("%d %d" , &x , &y);
          v[x].pb(y);
          v[y].pb(x);
     }
     dfs(1);

}


#include <bits/stdc++.h>
using namespace std;
#define MOD 1000000007
#define PI 3.14159265358979323846
#define forn(i,s,n) for(int i=s ; i<n ; i++)
#define fornr(i,s,n) for(int i=n ; i>s ; i--)
#define mp make_pair
#define pb push_back
#define fr first
#define sc second
const int SIZE=4000000;
const int OO = (int)1e9;
typedef vector<int> vi;
typedef unsigned long long int ll;
typedef pair<int , int > ii;
typedef pair<pair<int, double> , int > iii;

bool comp(iii a , iii b){
     return a.first.first * b.first.second < a.first.second * b.first.first ;
}
map<ii, bool > mpp;
vi v[100009];

int dfs(int node){
     vi adj;
     forn(i , 0 , v[node].size())if(!mpp[{node , v[node][i]}]){
          adj.pb(v[node][i]);
           mpp[{node , v[node][i]}]=1;
               mpp[{ v[node][i] , node}]=1;

     }
     vi un;
     forn(i , 0 , adj.size()){
          int ch = adj[i];

               int xx =  dfs(ch);
               if(xx==0){
                    un.pb(ch);
               }else {
                    printf("%d %d %d\n" , node , ch , xx);
               }

     }
          while(un.size()>=2){
               int a = un.back();
               un.pop_back();
               int b = un.back();

               un.pop_back();
               printf("%d %d %d\n" , a , node ,b);

          }
          if(!un.size()){
               return 0;
          }else {
               int chh = un.back();
               un.pop_back();
               return chh;
          }

}
int main(){
     int n , m;
     scanf("%d %d" , &n , &m);
     if(m&1)return puts("No solution");
     forn(i , 0 , m){
          int x , y;
          scanf("%d %d" , &x , &y);
          v[x].pb(y);
          v[y].pb(x);
     }
     dfs(1);

}


#include <bits/stdc++.h>
using namespace std;
#define MOD 1000000007
#define PI 3.14159265358979323846
#define forn(i,s,n) for(int i=s ; i<n ; i++)
#define fornr(i,s,n) for(int i=n ; i>s ; i--)
#define mp make_pair
#define pb push_back
#define fr first
#define sc second
const int SIZE=4000000;
const int OO = (int)1e9;
typedef vector<int> vi;
typedef unsigned long long int ll;
typedef pair<int , int > ii;
typedef pair<pair<int, double> , int > iii;

bool comp(iii a , iii b){
     return a.first.first * b.first.second < a.first.second * b.first.first ;
}
map<ii, bool > mpp;
vi v[100009];
const int UP = 0 , RIGHT = 1 , DOWN =2 , LEFT = 3;
int dfs(int node){
     vi un;
     forn(i , 0 , v[node].size()){
          int ch = v[node][i];
          if(!mpp[{node , ch}]){
               mpp[{node , ch }]=1;
               mpp[{ch , node}]=1;
               int xx =  dfs(ch);
               if(xx==0){
                    un.pb(ch);
               }else {
                    printf("%d %d %d\n" , node , ch , xx);
               }
          }

     }
          while(un.size()>=2){
               int a = un.back();
               un.pop_back();
               int b = un.back();

               un.pop_back();
               printf("%d %d %d\n" , a , b , node);

          }
          if(!un.size()){
               return 0;
          }else {
               int chh = un.back();
               return chh;
          }

}
int main(){
     int n , m;
     scanf("%d %d" , &n , &m);
     if(m&1)return puts("No solution");
     forn(i , 0 , m){
          int x , y;
          scanf("%d %d" , &x , &y);
          v[x].pb(y);
          v[y].pb(x);
     }
     dfs(1);

}