← Home
```go
package main

import (
	"bufio"
	"fmt"
	"os"
)

type DSU struct {
	p []int
	r []int
}

func NewDSU(n int) *DSU {
	p := make([]int, n+1)
	r := make([]int, n+1)
	for i := 1; i <= n; i++ {
		p[i] = i
	}
	return &DSU{p: p, r: r}
}

func (d *DSU) Find(x int) int {
	if d.p[x] != x {
		d.p[x] = d.Find(d.p[x])
	}
	return d.p[x]
}

func (d *DSU) Union(a, b int) {
	ra := d.Find(a)
	rb := d.Find(b)
	if ra == rb {
		return
	}
	if d.r[ra] < d.r[rb] {
		d.p[ra] = rb
	} else if d.r[ra] > d.r[rb] {
		d.p[rb] = ra
	} else {
		d.p[rb] = ra
		d.r[ra]++
	}
}

type Edge struct {
	u, v int
}

type stackNode struct {
	v      int
	inEdge int
}

type circItem struct {
	id   int
	tail int
}

type FastScanner struct {
	r *bufio.Reader
}

func NewFastScanner() *FastScanner {
	return &FastScanner{r: bufio.NewReaderSize(os.Stdin, 1<<20)}
}

func (fs *FastScanner) NextInt() int {
	sign := 1
	val := 0
	b, _ := fs.r.ReadByte()
	for (b < '0' || b > '9') && b != '-' {
		b, _ = fs.r.ReadByte()
	}
	if b == '-' {
		sign = -1
		b, _ = fs.r.ReadByte()
	}
	for b >= '0' && b <= '9' {
		val = val*10 + int(b-'0')
		b, _ = fs.r.ReadByte()
	}
	return sign * val
}

func main() {
	in := NewFastScanner()
	out := bufio.NewWriterSize(os.Stdout, 1<<20)
	defer out.Flush()

	n := in.NextInt()
	m := in.NextInt()

	dsu := NewDSU(n)
	deg := make([]int, n+1)
	edges := make([]Edge, 0, m*2)

	origM := m
	for i := 0; i < origM; i++ {
		u := in.NextInt()
		v := in.NextInt()
		edges = append(edges, Edge{u: u, v: v})
		deg[u]++
		deg[v]++
		if u != v {
			dsu.Union(u, v)
		}
	}

	// Map DSU roots to compact component indices
	root2idx := make(map[int]int)
	compAnyVertex := make([]int, 0)
	for v := 1; v <= n; v++ {
		r := dsu.Find(v)
		if _, ok := root2idx[r]; !ok {
			root2idx[r] = len(compAnyVertex)
			compAnyVertex = append(compAnyVertex, v)
		}
	}
	C := len(compAnyVertex)
	compEdges := make([]int, C)
	oddList := make([][]int, C)

	for i := 0; i < origM; i++ {
		u := edges[i].u
		r := root2idx[dsu.Find(u)]
		compEdges[r]++
	}
	for v := 1; v <= n; v++ {
		if deg[v]&1 == 1 {
			r := root2idx[dsu.Find(v)]
			oddList[r] = append(oddList[r], v)
		}
	}

	// Components with odd-degree vertices (B) and without (A)
	compsB := make([]int, 0)
	for i := 0; i < C; i++ {
		if len(oddList[i]) > 0 {
			compsB = append(compsB, i)
		}
	}

	// Compute s = XOR over B of (e_i %2) XOR ((o_i/2) %2)
	s := 0
	for _, ci := range compsB {
		oi := len(oddList[ci])
		ti := (compEdges[ci] & 1) ^ ((oi / 2) & 1)
		s ^= ti
	}

	// Pair odd vertices: connect all compsB into a chain, then pair remaining in the merged big group
	addEdge := func(u, v int) {
		edges = append(edges, Edge{u: u, v: v})
	}

	k := len(compsB)
	if k >= 2 {
		for i := 0; i < k-1; i++ {
			u := oddList[compsB[i]][len(oddList[compsB[i]])-1]
			oddList[compsB[i]] = oddList[compsB[i]][:len(oddList[compsB[i]])-1]
			v := oddList[compsB[i+1]][len(oddList[compsB[i+1]])-1]
			oddList[compsB[i+1]] = oddList[compsB[i+1]][:len(oddList[compsB[i+1]])-1]
			addEdge(u, v)
		}
	}
	// Pool remaining odd vertices across all compsB and pair them
	if k >= 1 {
		pool := make([]int, 0)
		for _, ci := range compsB {
			for len(oddList[ci]) > 0 {
				last := oddList[ci][len(oddList[ci])-1]
				oddList[ci] = oddList[ci][:len(oddList[ci])-1]
				pool = append(pool, last)
			}
		}
		for i := 0; i+1 < len(pool); i += 2 {
			addEdge(pool[i], pool[i+1])
		}
	}

	// Add loops to components in A (o_i == 0) with odd number of edges
	for i := 0; i < C; i++ {
		if len(oddList[i]) == 0 {
			if (compEdges[i] & 1) == 1 {
				v := compAnyVertex[i]
				addEdge(v, v)
			}
		}
	}

	// If s == 1, add one loop in the merged big group if it exists
	if k >= 1 && (s&1) == 1 {
		v := compAnyVertex[compsB[0]]
		addEdge(v, v)
	}

	// Build adjacency for Euler traversal
	p := len(edges)
	adj := make([][]int, n+1)
	for id := 0; id < p; id++ {
		u := edges[id].u
		v := edges[id].v
		adj[u] = append(adj[u], id)
		adj[v] = append(adj[v], id)
	}

	used := make([]bool, p)
	nextIdx := make([]int, n+1)
	from := make([]int, p)
	to := make([]int, p)

	for start := 1; start <= n; start++ {
		if len(adj[start]) == 0 {
			continue
		}
		st := make([]stackNode, 0, 32)
		st = append(st, stackNode{v: start, inEdge: -1})
		circuit := make([]circItem, 0, 32)
		progress := false

		for len(st) > 0 {
			u := st[len(st)-1].v
			for nextIdx[u] < len(adj[u]) && used[adj[u][nextIdx[u]]] {
				nextIdx[u]++
			}
			if nextIdx[u] == len(adj[u]) {
				inc := st[len(st)-1].inEdge
				st = st[:len(st)-1]
				if inc != -1 {
					parent := u
					if len(st) > 0 {
						parent = st[len(st)-1].v
					}
					circuit = append(circuit, circItem{id: inc, tail: parent})
					progress = true
				}
			} else {
				eid := adj[u][nextIdx[u]]
				nextIdx[u]++
				if used[eid] {
					continue
				}
				used[eid] = true
				a := edges[eid].u
				b := edges[eid].v
				w := b
				if u == b {
					w = a
				}
				st = append(st, stackNode{v: w, inEdge: eid})
			}
		}

		if progress {
			flip := false
			for i := 0; i < len(circuit); i++ {
				id := circuit[i].id
				tail := circuit[i].tail
				a := edges[id].u
				b := edges[id].v
				other := tail
				if a == b {
					other = tail
				} else if tail == a {
					other = b
				} else {
					other = a
				}
				if !flip {
					from[id] = tail
					to[id] = other
				} else {
					from[id] = other
					to[id] = tail
				}
				flip = !flip
			}
		}
	}

	// Output
	fmt.Fprintln(out, p)
	for i := 0; i < p; i++ {
		if from[i] == 0 && to[i] == 0 {
			// In case of isolated loopless vertices (shouldn't happen), default any direction
			fmt.Fprintln(out, edges[i].u, edges[i].v)
		} else {
			fmt.Fprintln(out, from[i], to[i])
		}
	}
}
```