Problem:
Score : 700 points

Problem Statement

You are given a simple connected undirected graph with N vertices and M edges. The vertices are numbered 1 to N, and the i-th edge connects Vertex A_i and Vertex B_i.
Takahashi will assign one of the two possible directions to each of the edges in the graph to make a directed graph.
Determine if it is possible to make a directed graph with an even number of edges going out from every vertex. If the answer is yes, construct one such graph.

Notes

An undirected graph is said to be simple when it contains no self-loops or multiple edges.

Constraints

2 \leq N \leq 10^5

N-1 \leq M \leq 10^5

1 \leq A_i,B_i \leq N (1\leq i\leq M)

The given graph is simple and connected.

Input

Input is given from Standard Input in the following format:

N M
A_1 B_1
:
A_M B_M

Output

If it is impossible to assign directions to satisfy the requirement, print -1.
Otherwise, print an assignment of directions that satisfies the requirement, in the following format:

C_1 D_1
:
C_M D_M

Here each pair (C_i, D_i) means that there is an edge directed from Vertex C_i to Vertex D_i. The edges may be printed in any order.

Sample Input 1

4 4
1 2
2 3
3 4
4 1

Sample Output 1

1 2
1 4
3 2
3 4

After this assignment of directions, Vertex 1 and 3 will each have two outgoing edges, and Vertex 2 and 4 will each have zero outgoing edges.

Sample Input 2

5 5
1 2
2 3
3 4
2 5
4 5

Sample Output 2

-1

Solution in Go (1.6) (judge verdict: Accepted)

// https://atcoder.jp/contests/agc035/tasks/agc035_b

package main

import (
	"bufio"
	"bytes"
	"fmt"
	"os"
	"reflect"
	"runtime"
	"sort"
	"strconv"
	"strings"
)

type UnionFind struct {
	// for children, the value is its parent index. for root, the value is -1 * the size of the group
	parents []int
}

func NewUnionFind(n int) *UnionFind {
	uf := &UnionFind{}

	uf.parents = make([]int, n)

	for i := range uf.parents {
		uf.parents[i] = -1
	}

	return uf
}

func (uf *UnionFind) root(x int) int {
	if uf.parents[x] < 0 {
		return x
	}

	r := uf.root(uf.parents[x])
	uf.parents[x] = r
	return r
}

func (uf *UnionFind) same(x, y int) bool {
	return uf.root(x) == uf.root(y)
}

func (uf *UnionFind) merge(x, y int) {
	xr := uf.root(x)
	yr := uf.root(y)

	if xr == yr {
		return
	}

	// make less index one as a root
	if xr > yr {
		xr, yr = yr, xr
	}

	uf.parents[xr] += uf.parents[yr]
	uf.parents[yr] = xr
}

func (uf *UnionFind) size(x int) int {
	return -uf.parents[uf.root(x)]
}

func (uf *UnionFind) groupCount() (res int) {
	for _, parent := range uf.parents {
		if parent < 0 {
			res++
		}
	}

	return
}

// コストを考えない Kruskal
func GetMinEdgeList(edgeList [][]int) [][]int {
	uf := NewUnionFind(len(edgeList))

	minEdgeList := make([][]int, len(edgeList))
	for i := range minEdgeList {
		minEdgeList[i] = make([]int, 0)
	}

	for u, uEdges := range edgeList {
		for _, v := range uEdges {
			if u > v || uf.same(u, v) {
				continue
			}

			minEdgeList[u] = append(minEdgeList[u], v)
			minEdgeList[v] = append(minEdgeList[v], u)
			uf.merge(u, v)
		}
	}

	return minEdgeList
}

// big - small. small はソートされている必要がある
func edgeListDiff(big [][]int, small [][]int) [][]int {
	res := make([][]int, len(big))

	for i := range res {
		res[i] = make([]int, 0)
	}

	for u, uEdgeList := range big {
		for _, v := range uEdgeList {
			i := sort.SearchInts(small[u], v)

			if i < len(small[u]) && small[u][i] == v {
				continue
			}

			res[u] = append(res[u], v)
		}
	}

	return res
}

// d: debug IO. it can print debug in test.
func solve(io *Io, d *Io) {
	N := io.NextInt()
	M := io.NextInt()

	edgeList := make([][]int, N)
	for i := range edgeList {
		edgeList[i] = make([]int, 0)
	}

	for i := 0; i < M; i++ {
		a := io.NextInt() - 1
		b := io.NextInt() - 1
		edgeList[a] = append(edgeList[a], b)
		edgeList[b] = append(edgeList[b], a)
	}

	// 1. 最小全域木を作る
	// 2. それ以外の辺については適当に方向を決めてしまう
	// 3. 最小全域木について根を適当に設けて、木の子から向きを確定させていく

	// 1. 最小全域木を作る
	minEdgeList := GetMinEdgeList(edgeList)

	for _, uEdges := range minEdgeList {
		sort.Ints(uEdges)
	}

	notMinEdgeList := edgeListDiff(edgeList, minEdgeList)

	resEdgeList := make([][]int, N)
	for u := range resEdgeList {
		resEdgeList[u] = make([]int, 0)
	}

	// 2. それ以外の辺については適当に方向を決めてしまう
	for u, uEdges := range notMinEdgeList {
		for _, v := range uEdges {
			if u > v {
				continue
			}

			// u -> v
			resEdgeList[u] = append(resEdgeList[u], v)
		}
	}

	// 3. 最小全域木について根を適当に設けて、木の子から向きを確定させていく
	var rec func(u, p int)

	rec = func(u, p int) {
		_ = edgeList[0]
		for _, v := range minEdgeList[u] {
			if v == p {
				continue
			}

			rec(v, u)
		}

		if p == -1 {
			return
		}

		curOutCt := len(resEdgeList[u])
		var from, to int

		if curOutCt%2 == 1 {
			from, to = u, p
		} else {
			from, to = p, u
		}

		resEdgeList[from] = append(resEdgeList[from], to)
	}

	rec(0, -1)

	if len(resEdgeList[0])%2 != 0 {
		io.Println(-1)
		return
	}

	for u, uEdges := range resEdgeList {
		for _, v := range uEdges {
			io.Println(u+1, v+1)
		}
	}
}

func main() {
	io := NewIo()
	defer io.Flush()
	solve(io, nil)
}

/* IO Helpers */

// Io combines reader, writer, & tokens as the state when processing the input
type Io struct {
	reader    *bufio.Reader
	writer    *bufio.Writer
	tokens    []string
	nextToken int
}

// NewIo creates Io with Stdin & Stdout
func NewIo() *Io {
	return &Io{
		reader: bufio.NewReader(os.Stdin),
		writer: bufio.NewWriter(os.Stdout),
	}
}

// Flush calls the writer's Flush
func (io *Io) Flush() {
	io.writer.Flush()
}

// NextLine returns the string from reader.ReadLine()
func (io *Io) NextLine() string {
	if io.nextToken < len(io.tokens) {
		panic("io.nextToken < len(io.tokens)")
	}

	var buffer bytes.Buffer

	for {
		line, isPrefix, err := io.reader.ReadLine()
		if err != nil {
			panic(err)
		}
		buffer.Write(line)
		if !isPrefix {
			break
		}
	}

	return buffer.String()
}

// NextLines returns []string from next n lines
func (io *Io) NextLines(n int) []string {
	res := make([]string, n)
	for i := 0; i < n; i++ {
		res[i] = io.NextLine()
	}
	return res
}

// Next returns the string token (partial string of the line divided by spaces)
func (io *Io) Next() string {
	if io.nextToken >= len(io.tokens) {
		line := io.NextLine()
		io.tokens = strings.Fields(line)
		io.nextToken = 0
	}

	res := io.tokens[io.nextToken]
	io.nextToken++
	return res
}

// NextStrings returns the []string from the next n tokens
func (io *Io) NextStrings(n int) []string {
	res := make([]string, n)
	for i := 0; i < n; i++ {
		res[i] = io.Next()
	}
	return res
}

// NextRunes returns next string as []rune
func (io *Io) NextRunes() []rune {
	return []rune(io.Next())
}

// NextInt returns the int from the next token
func (io *Io) NextInt() int {
	res, err := strconv.Atoi(io.Next())
	if err != nil {
		panic(err)
	}
	return res
}

// NextInts returns the []int from the next n tokens
func (io *Io) NextInts(n int) []int {
	res := make([]int, n)
	for i := 0; i < n; i++ {
		res[i] = io.NextInt()
	}
	return res
}

// NextFloat returns the float64 from the next token
func (io *Io) NextFloat() float64 {
	res, err := strconv.ParseFloat(io.Next(), 64)
	if err != nil {
		panic(err)
	}
	return res
}

// NextFloats returns the []float64 from the next n tokens
func (io *Io) NextFloats(n int) []float64 {
	res := make([]float64, n)
	for i := 0; i < n; i++ {
		res[i] = io.NextFloat()
	}
	return res
}

// Println prints the input to the writer in an easy-to-see form
func (io *Io) Println(a ...interface{}) {
	var values []string
	for i := 0; i < len(a); i++ {
		values = append(values, "%v")
	}
	io.Printfln(strings.Join(values, " "), a...)
}

// Print calls Fprint to the writer
func (io *Io) Print(a interface{}) {
	fmt.Fprint(io.writer, a)
}

// Printf calls Fprintf to the writer
func (io *Io) Printf(format string, a ...interface{}) {
	fmt.Fprintf(io.writer, format, a...)
}

// Printfln calls Fprint to the writer
func (io *Io) Printfln(format string, a ...interface{}) {
	fmt.Fprintf(io.writer, format+"\n", a...)
}

// PrintInts prints ints with space and new line at the end
func (io *Io) PrintInts(ints []int) {
	for i, e := range ints {
		io.Print(e)

		if i == len(ints)-1 {
			io.Println()
		} else {
			io.Print(" ")
		}
	}
}

// Debug calls Println and Flush immediately
func (io *Io) Debug(a ...interface{}) {
	if io == nil {
		return
	}

	io.Println(a...)
	io.Flush()
}

// Assert checks the value equality for debug
func (io *Io) Assert(a, b interface{}) {
	if io == nil {
		return
	}

	if !reflect.DeepEqual(a, b) {
		_, _, line, _ := runtime.Caller(1)
		io.Debug("Diff:", line, "\na:", a, "\nb:", b)
	}
}

/* Math Helpers */

// MOD is 10^9 + 7
const MOD = 1000000007

// Max of the ints
func Max(numbers ...int) int {
	max := numbers[0]
	for i, number := range numbers {
		if i == 0 {
			continue
		}
		if number > max {
			max = number
		}
	}
	return max
}

// Min of the ints
func Min(numbers ...int) int {
	min := numbers[0]
	for i, number := range numbers {
		if i == 0 {
			continue
		}
		if min > number {
			min = number
		}
	}
	return min
}

// Sum of the ints
func Sum(numbers ...int) int {
	sum := 0

	for _, number := range numbers {
		sum += number
	}

	return sum
}

// Pow calculates the pow for int with O(log e)
func Pow(a, e int) int {
	if a < 0 || e < 0 {
		panic(fmt.Sprintf("Pow was called for a < 0 or e < 0, a: %d, e: %d", a, e))
	}

	if e == 0 {
		return 1
	}

	if e%2 == 0 {
		half := Pow(a, e/2)
		return half * half
	}

	return a * Pow(a, e-1)
}

// Abs returns the absolute value of the input
func Abs(a int) int {
	if a < 0 {
		return -a
	}

	return a
}

/* Structure Helpers */

// Set is orderless List
type Set map[interface{}]struct{}

// NewSet returns empty Set
func NewSet() *Set {
	return &Set{}
}

// Add the value to the set
func (set *Set) Add(value interface{}) {
	(*set)[value] = struct{}{}
}

// Includes check the set has the value
func (set *Set) Includes(value interface{}) bool {
	_, included := (*set)[value]
	return included
}

// Remove deletes the value from the set if exists
func (set *Set) Remove(value interface{}) {
	if !set.Includes(value) {
		return
	}

	delete(*set, value)
}

// ImmutableSort returns sorted slice without mutating original one
func ImmutableSort(slice []int) []int {
	res := make([]int, len(slice))
	copy(res, slice)
	sort.Ints(res)
	return res
}

/* Util helpers */

// Ternary is like `cond ? a : b`. should assert the returned value like `Ternary(cond, a, b).(int)`
func Ternary(cond bool, a, b interface{}) interface{} {
	if cond {
		return a
	}

	return b
}

// TernaryInt uses Ternary and assert the value as int
func TernaryInt(cond bool, a, b int) int {
	return Ternary(cond, a, b).(int)
}

// TernaryString uses Ternary and assert the value as string
func TernaryString(cond bool, a, b string) string {
	return Ternary(cond, a, b).(string)
}