← Home
package main

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

type Node struct {
	l, r *Node
	sum  int
}

func getSum(n *Node) int {
	if n == nil {
		return 0
	}
	return n.sum
}

func update(root *Node, l, r, idx, val int) *Node {
	if l == r {
		return &Node{sum: val}
	}
	mid := l + (r-l)/2
	res := &Node{}
	if root != nil {
		res.l = root.l
		res.r = root.r
	}
	if idx <= mid {
		res.l = update(res.l, l, mid, idx, val)
	} else {
		res.r = update(res.r, mid+1, r, idx, val)
	}
	res.sum = getSum(res.l) + getSum(res.r)
	return res
}

func query(root *Node, l, r, idx int) int {
	if root == nil {
		return 0
	}
	if l == r {
		return root.sum
	}
	mid := l + (r-l)/2
	if idx <= mid {
		return query(root.l, l, mid, idx)
	}
	return query(root.r, mid+1, r, idx)
}

func getOnes(root *Node, l, r int, ones *[]int) {
	if root == nil || root.sum == 0 {
		return
	}
	if l == r {
		*ones = append(*ones, l)
		return
	}
	mid := l + (r-l)/2
	getOnes(root.l, l, mid, ones)
	getOnes(root.r, mid+1, r, ones)
}

type State struct {
	u    int
	c    int
	root *Node
}

type Info struct {
	prevU int
	prevC int
}

func main() {
	reader := bufio.NewReader(os.Stdin)
	var n, m int
	if _, err := fmt.Fscan(reader, &n, &m); err != nil {
		return
	}

	adj := make([][]int, n+1)
	for i := 0; i < m; i++ {
		var u, v int
		fmt.Fscan(reader, &u, &v)
		adj[u] = append(adj[u], v)
		adj[v] = append(adj[v], u)
	}

	visited := make([][2]bool, n+1)
	parent := make([][2]Info, n+1)

	next := make([]int, n+2)
	prev := make([]int, n+2)
	for i := 2; i <= n; i++ {
		next[i] = i + 1
		prev[i] = i - 1
	}
	head := 2
	prev[2] = 0
	next[n] = n + 1

	removeNode := func(v int) {
		p := prev[v]
		nxt := next[v]
		if p != 0 {
			next[p] = nxt
		} else {
			head = nxt
		}
		if nxt != n+1 && nxt != 0 {
			prev[nxt] = p
		}
		prev[v] = 0
		next[v] = 0
	}

	isAdj := make([]bool, n+1)

	q := []State{{u: 1, c: 0, root: nil}}
	visited[1][0] = true

	found := false
	for len(q) > 0 {
		curr := q[0]
		q = q[1:]

		u := curr.u
		c := curr.c
		root := curr.root

		if u == n {
			found = true
			break
		}

		for _, v := range adj[u] {
			isAdj[v] = true
		}

		newRoot := update(root, 1, n, u, 1-c)

		for _, v := range adj[u] {
			dv := query(root, 1, n, v)
			if dv == c {
				if !visited[v][c] {
					visited[v][c] = true
					parent[v][c] = Info{u, c}
					q = append(q, State{v, c, newRoot})
					if c == 0 && prev[v] != 0 || head == v {
						removeNode(v)
					}
				}
			}
		}

		if c == 0 {
			var ones []int
			getOnes(root, 1, n, &ones)
			for _, v := range ones {
				if v == u {
					continue
				}
				if !isAdj[v] {
					if !visited[v][1] {
						visited[v][1] = true
						parent[v][1] = Info{u, c}
						q = append(q, State{v, 1, newRoot})
					}
				}
			}
		} else {
			var toRemove []int
			for v := head; v != 0 && v <= n; v = next[v] {
				if v == u {
					continue
				}
				if !isAdj[v] {
					if query(root, 1, n, v) == 0 {
						visited[v][0] = true
						toRemove = append(toRemove, v)
						parent[v][0] = Info{u, c}
						q = append(q, State{v, 0, newRoot})
					}
				}
			}
			for _, v := range toRemove {
				removeNode(v)
			}
		}

		for _, v := range adj[u] {
			isAdj[v] = false
		}
	}

	if !found && !visited[n][0] && !visited[n][1] {
		fmt.Println("-1")
		return
	}

	currU := n
	currC := 0
	if !visited[n][0] {
		currC = 1
	}

	path := []int{n}
	for currU != 1 || currC != 0 {
		p := parent[currU][currC]
		path = append(path, p.prevU)
		currU = p.prevU
		currC = p.prevC
	}

	fmt.Println(len(path) - 1)
	writer := bufio.NewWriter(os.Stdout)
	for i := len(path) - 1; i >= 0; i-- {
		fmt.Fprintf(writer, "%d ", path[i])
	}
	fmt.Fprintln(writer)
	writer.Flush()
}