```go
package main
import (
"bufio"
"fmt"
"os"
"strconv"
)
type State struct {
u, k int
}
type DList struct {
head int
next, prev []int
}
func newDList(n int) *DList {
return &DList{
head: 0,
next: make([]int, n+1),
prev: make([]int, n+1),
}
}
func (l *DList) push(x int) {
if l.head != 0 {
l.prev[l.head] = x
}
l.next[x] = l.head
l.prev[x] = 0
l.head = x
}
func (l *DList) remove(x int) {
p := l.prev[x]
n := l.next[x]
if p != 0 {
l.next[p] = n
} else {
l.head = n
}
if n != 0 {
l.prev[n] = p
}
l.next[x] = 0
l.prev[x] = 0
}
func main() {
scanner := bufio.NewScanner(os.Stdin)
scanner.Buffer(make([]byte, 1024*1024), 1024*1024*10)
scanner.Split(bufio.ScanWords)
if !scanner.Scan() {
return
}
n, _ := strconv.Atoi(scanner.Text())
scanner.Scan()
m, _ := strconv.Atoi(scanner.Text())
adj := make([][]int, n+1)
for i := 0; i < m; i++ {
scanner.Scan()
u, _ := strconv.Atoi(scanner.Text())
scanner.Scan()
v, _ := strconv.Atoi(scanner.Text())
adj[u] = append(adj[u], v)
adj[v] = append(adj[v], u)
}
dist := make([][2]int, n+1)
parent := make([][2]State, n+1)
for i := 1; i <= n; i++ {
dist[i][0] = -1
dist[i][1] = -1
}
dist[1][0] = 0
S0 := newDList(n)
S1 := newDList(n)
inS0 := make([]bool, n+1)
inS1 := make([]bool, n+1)
for i := 2; i <= n; i++ {
S0.push(i)
inS0[i] = true
}
S1.push(1)
inS1[1] = true
isOpen := make([]bool, n+1)
queue := make([]State, 0, 2*n)
queue = append(queue, State{u: 1, k: 0})
for len(queue) > 0 {
curr := queue[0]
queue = queue[1:]
u := curr.u
K := curr.k
for _, v := range adj[u] {
isOpen[v] = true
}
if K == 0 {
currNode := S1.head
for currNode != 0 {
nxt := S1.next[currNode]
if currNode != u && !isOpen[currNode] {
v := currNode
inS1[v] = false
S1.remove(v)
dist[v][1] = dist[u][0] + 1
parent[v][1] = State{u: u, k: 0}
queue = append(queue, State{u: v, k: 1})
}
currNode = nxt
}
for _, v := range adj[u] {
if inS0[v] {
inS0[v] = false
S0.remove(v)
inS1[v] = true
S1.push(v)
dist[v][0] = dist[u][0] + 1
parent[v][0] = State{u: u, k: 0}
if v == n {
printPath(parent, n)
return
}
queue = append(queue, State{u: v, k: 0})
}
}
} else {
currNode := S0.head
for currNode != 0 {
nxt := S0.next[currNode]
if currNode != u && !isOpen[currNode] {
v := currNode
inS0[v] = false
S0.remove(v)
inS1[v] = true
S1.push(v)
dist[v][0] = dist[u][1] + 1
parent[v][0] = State{u: u, k: 1}
if v == n {
printPath(parent, n)
return
}
queue = append(queue, State{u: v, k: 0})
}
currNode = nxt
}
for _, v := range adj[u] {
if inS1[v] {
inS1[v] = false
S1.remove(v)
dist[v][1] = dist[u][1] + 1
parent[v][1] = State{u: u, k: 1}
queue = append(queue, State{u: v, k: 1})
}
}
}
for _, v := range adj[u] {
isOpen[v] = false
}
}
fmt.Println("-1")
}
func printPath(parent [][2]State, n int) {
path := []int{}
curr := State{u: n, k: 0}
for curr.u != 1 || curr.k != 0 {
path = append(path, curr.u)
curr = parent[curr.u][curr.k]
}
path = append(path, 1)
fmt.Println(len(path) - 1)
out := bufio.NewWriter(os.Stdout)
for i := len(path) - 1; i >= 0; i-- {
fmt.Fprintf(out, "%d ", path[i])
}
fmt.Fprintln(out)
out.Flush()
}
```