package main

import (
	"bufio"
	. "fmt"
	"io"
	"os"
)

func run(_r io.Reader, _w io.Writer) {
	in := bufio.NewReader(_r)
	out := bufio.NewWriter(_w)
	defer out.Flush()

	var n, m, k int
	Fscan(in, &n, &m)
	g := make([][]int, n)
	rg := make([][]int, n)
	for i := 0; i < m; i++ {
		var v, w int
		Fscan(in, &v, &w)
		v--
		w--
		g[v] = append(g[v], w)
		rg[w] = append(rg[w], v)
	}
	Fscan(in, &k)
	path := make([]int, k)
	for i := range path {
		Fscan(in, &path[i])
		path[i]--
	}
	st, end := path[0], path[k-1]

	// 最小：从终点看，每一步是否离终点更近了 dfswithdepth 相邻dep之差为1
	// 最大：

	vis := make([]bool, n)
	vis[st] = true
	dep := make([]int, n)
	type pair struct{ v, dep int }
	queue := []pair{{st, 0}}
	for len(queue) > 0 {
		var p pair
		p, queue = queue[0], queue[1:]
		dep[p.v] = p.dep
		for _, w := range g[p.v] {
			if !vis[w] {
				vis[w] = true
				queue = append(queue, pair{w, p.dep + 1})
			}
		}
	}

	vis = make([]bool, n)
	vis[end] = true
	rdep := make([]int, n)
	queue = []pair{{end, 0}}
	for len(queue) > 0 {
		var p pair
		p, queue = queue[0], queue[1:]
		rdep[p.v] = p.dep
		for _, w := range rg[p.v] {
			if !vis[w] {
				vis[w] = true
				queue = append(queue, pair{w, p.dep + 1})
			}
		}
	}

	minAns := 0
	for i := 1; i < k; i++ {
		v, last := path[i], path[i-1]
		if rdep[v]-rdep[last] >= 0 {
			minAns++
		}
	}

	maxAns := 0
	for i := 0; i < k-1; i++ {
		v := path[i]
		next := path[i+1]
		if rdep[v]-rdep[next] <= 0 {
			maxAns++
			continue
		}
		for _, w := range g[v] {
			if w != next && rdep[w] == rdep[next] {
				maxAns++
				break
			}
		}
	}

	Fprintln(out, minAns, maxAns)
}

func main() { run(os.Stdin, os.Stdout) }

/*
URL:
https://codeforces.com/contest/1320/problem/B
*/

package main

import (
	"bufio"
	"errors"
	"fmt"
	"io"
	"math"
	"os"
	"strconv"
)

var (
	n, m int
	k    int
	P    []int

	G  [200000 + 50][]int
	RG [200000 + 50][]int

	cnts [200000 + 50]int
)

func main() {
	defer stdout.Flush()

	n, m = readi2()
	for i := 0; i < m; i++ {
		u, v := readi2()
		u--
		v--

		G[v] = append(G[v], u)
		RG[u] = append(RG[u], v)
	}
	k = readi()
	P = readis(k)
	for i := 0; i < k; i++ {
		P[i]--
	}

	dp, _ := SSSPByBFS(P[k-1], n, G[:n], 1)

	for i := 0; i < n; i++ {
		cnts[dp[i]]++
	}

	mini, maxi := 0, 0
	for i := 0; i < k-1; i++ {
		cid, nid := P[i], P[i+1]

		if dp[cid]-1 < dp[nid] {
			mini++
			maxi++
			continue
		}

		ok := false
		for _, e := range RG[cid] {
			if dp[cid] == dp[e]+1 && e != nid {
				ok = true
				break
			}
		}
		if ok {
			maxi++
		}
	}

	fmt.Println(mini, maxi)
}

// verified by https://codeforces.com/contest/1320/problem/B
func SSSPByBFS(sid int, n int, AG [][]int, edgeCost int) (dp []int, visited []bool) {
	const INF_SSSP = 1 << uint(30)

	dp = make([]int, n)
	visited = make([]bool, n)

	for i := 0; i < n; i++ {
		dp[i] = INF_SSSP
		visited[i] = false
	}

	Q := []Node{}
	dp[sid] = 0
	visited[sid] = true
	Q = append(Q, Node{id: sid, cost: dp[sid]})

	for len(Q) > 0 {
		cnode := Q[0]
		Q = Q[1:]

		for _, nid := range AG[cnode.id] {
			if visited[nid] {
				continue
			}

			dp[nid] = cnode.cost + edgeCost
			visited[nid] = true
			Q = append(Q, Node{id: nid, cost: dp[nid]})
		}
	}

	return dp, visited
}

type Node struct {
	id, cost int
}

/*******************************************************************/

/********** common constants **********/

const (
	MOD = 1000000000 + 7
	// MOD          = 998244353
	ALPH_N  = 26
	INF_I64 = math.MaxInt64
	INF_B60 = 1 << 60
	INF_I32 = math.MaxInt32
	INF_B30 = 1 << 30
	NIL     = -1
	EPS     = 1e-10
)

/********** bufio setting **********/

func init() {
	// bufio.ScanWords <---> bufio.ScanLines
	reads = newReadString(os.Stdin, bufio.ScanWords)
	stdout = bufio.NewWriter(os.Stdout)
}

// mod can calculate a right residual whether value is positive or negative.
func mod(val, m int) int {
	res := val % m
	if res < 0 {
		res += m
	}
	return res
}

// min returns the min integer among input set.
// This function needs at least 1 argument (no argument causes panic).
func min(integers ...int) int {
	m := integers[0]
	for i, integer := range integers {
		if i == 0 {
			continue
		}
		if m > integer {
			m = integer
		}
	}
	return m
}

// max returns the max integer among input set.
// This function needs at least 1 argument (no argument causes panic).
func max(integers ...int) int {
	m := integers[0]
	for i, integer := range integers {
		if i == 0 {
			continue
		}
		if m < integer {
			m = integer
		}
	}
	return m
}

// chmin accepts a pointer of integer and a target value.
// If target value is SMALLER than the first argument,
//	then the first argument will be updated by the second argument.
func chmin(updatedValue *int, target int) bool {
	if *updatedValue > target {
		*updatedValue = target
		return true
	}
	return false
}

// chmax accepts a pointer of integer and a target value.
// If target value is LARGER than the first argument,
//	then the first argument will be updated by the second argument.
func chmax(updatedValue *int, target int) bool {
	if *updatedValue < target {
		*updatedValue = target
		return true
	}
	return false
}

// sum returns multiple integers sum.
func sum(integers ...int) int {
	var s int
	s = 0

	for _, i := range integers {
		s += i
	}

	return s
}

// abs is integer version of math.Abs
func abs(a int) int {
	if a < 0 {
		return -a
	}
	return a
}

// pow is integer version of math.Pow
// pow calculate a power by Binary Power (二分累乗法(O(log e))).
func pow(a, e int) int {
	if a < 0 || e < 0 {
		panic(errors.New("[argument error]: PowInt does not accept negative integers"))
	}

	if e == 0 {
		return 1
	}

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

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

/********** FAU standard libraries **********/

//fmt.Sprintf("%b\n", 255) 	// binary expression

/********** I/O usage **********/

//str := reads()
//i := readi()
//X := readis(n)
//S := readrs()
//a := readf()
//A := readfs(n)

//str := ZeroPaddingRuneSlice(num, 32)
//str := PrintIntsLine(X...)

/*********** Input ***********/

var (
	// reads returns a WORD string.
	reads  func() string
	stdout *bufio.Writer
)

func newReadString(ior io.Reader, sf bufio.SplitFunc) func() string {
	r := bufio.NewScanner(ior)
	r.Buffer(make([]byte, 1024), int(1e+9)) // for Codeforces
	r.Split(sf)

	return func() string {
		if !r.Scan() {
			panic("Scan failed")
		}
		return r.Text()
	}
}

// readi returns an integer.
func readi() int {
	return int(_readInt64())
}
func readi2() (int, int) {
	return int(_readInt64()), int(_readInt64())
}
func readi3() (int, int, int) {
	return int(_readInt64()), int(_readInt64()), int(_readInt64())
}
func readi4() (int, int, int, int) {
	return int(_readInt64()), int(_readInt64()), int(_readInt64()), int(_readInt64())
}

// readll returns as integer as int64.
func readll() int64 {
	return _readInt64()
}
func readll2() (int64, int64) {
	return _readInt64(), _readInt64()
}
func readll3() (int64, int64, int64) {
	return _readInt64(), _readInt64(), _readInt64()
}
func readll4() (int64, int64, int64, int64) {
	return _readInt64(), _readInt64(), _readInt64(), _readInt64()
}

func _readInt64() int64 {
	i, err := strconv.ParseInt(reads(), 0, 64)
	if err != nil {
		panic(err.Error())
	}
	return i
}

// readis returns an integer slice that has n integers.
func readis(n int) []int {
	b := make([]int, n)
	for i := 0; i < n; i++ {
		b[i] = readi()
	}
	return b
}

// readlls returns as int64 slice that has n integers.
func readlls(n int) []int64 {
	b := make([]int64, n)
	for i := 0; i < n; i++ {
		b[i] = readll()
	}
	return b
}

// readf returns an float64.
func readf() float64 {
	return float64(_readFloat64())
}

func _readFloat64() float64 {
	f, err := strconv.ParseFloat(reads(), 64)
	if err != nil {
		panic(err.Error())
	}
	return f
}

// ReadFloatSlice returns an float64 slice that has n float64.
func readfs(n int) []float64 {
	b := make([]float64, n)
	for i := 0; i < n; i++ {
		b[i] = readf()
	}
	return b
}

// readrs returns a rune slice.
func readrs() []rune {
	return []rune(reads())
}

/*********** Output ***********/

// PrintIntsLine returns integers string delimited by a space.
func PrintIntsLine(A ...int) string {
	res := []rune{}

	for i := 0; i < len(A); i++ {
		str := strconv.Itoa(A[i])
		res = append(res, []rune(str)...)

		if i != len(A)-1 {
			res = append(res, ' ')
		}
	}

	return string(res)
}

// PrintIntsLine returns integers string delimited by a space.
func PrintInts64Line(A ...int64) string {
	res := []rune{}

	for i := 0; i < len(A); i++ {
		str := strconv.FormatInt(A[i], 10) // 64bit int version
		res = append(res, []rune(str)...)

		if i != len(A)-1 {
			res = append(res, ' ')
		}
	}

	return string(res)
}

// Printf is function for output strings to buffered os.Stdout.
// You may have to call stdout.Flush() finally.
func printf(format string, a ...interface{}) {
	fmt.Fprintf(stdout, format, a...)
}

/*********** Debugging ***********/

// debugf is wrapper of fmt.Fprintf(os.Stderr, format, a...)
func debugf(format string, a ...interface{}) {
	fmt.Fprintf(os.Stderr, format, a...)
}

// ZeroPaddingRuneSlice returns binary expressions of integer n with zero padding.
// For debugging use.
func ZeroPaddingRuneSlice(n, digitsNum int) []rune {
	sn := fmt.Sprintf("%b", n)

	residualLength := digitsNum - len(sn)
	if residualLength <= 0 {
		return []rune(sn)
	}

	zeros := make([]rune, residualLength)
	for i := 0; i < len(zeros); i++ {
		zeros[i] = '0'
	}

	res := []rune{}
	res = append(res, zeros...)
	res = append(res, []rune(sn)...)

	return res
}

package main

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

func main() {
	r := bufio.NewReader(os.Stdin)
	var n, m int
	fmt.Fscan(r, &n, &m)

	g := make([][]int, n)
	rg := make([][]int, n)
	for i := 0; i < m; i++ {
		var u, v int
		fmt.Fscan(r, &u, &v)
		u--
		v--
		g[u] = append(g[u], v)
		rg[v] = append(rg[v], u)
	}
	var k int
	fmt.Fscan(r, &k)
	p := make([]int, k)
	for i := 0; i < k; i++ {
		fmt.Fscan(r, &p[i])
		p[i]--
	}
	min, max := solve(g, rg, p)
	fmt.Println(min, max)
}

func solve(g, rg [][]int, p []int) (int, int) {
	k := len(p)
	d := dijkstra(rg, p[k-1])
	var min, max int
	for i := 0; i < k-1; i++ {
		if d[p[i]] != d[p[i+1]]+1 {
			min++
		}
		for _, v := range g[p[i]] {
			if v != p[i+1] && d[p[i]] == d[v]+1 {
				max++
				break
			}
		}
	}
	return min, max
}

func dijkstra(g [][]int, src int) []int {
	n := len(g)
	d := make([]int, n)
	for i := 0; i < n; i++ {
		d[i] = -1
	}
	d[src] = 0
	q := []int{src}
	for len(q) > 0 {
		cur := q[0]
		q = q[1:]
		for _, v := range g[cur] {
			if d[v] == -1 {
				d[v] = d[cur] + 1
				q = append(q, v)
			}
		}
	}
	return d
}

package main

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

func main() {
	r := bufio.NewReader(os.Stdin)
	var n, m int
	fmt.Fscan(r, &n, &m)

	g := make([][]int, n+1)
	rg := make([][]int, n+1)
	for i := 0; i < m; i++ {
		var u, v int
		fmt.Fscan(r, &u, &v)
		g[u] = append(g[u], v)
		rg[v] = append(rg[v], u)
	}
	var k int
	fmt.Fscan(r, &k)
	p := make([]int, k)
	for i := 0; i < k; i++ {
		fmt.Fscan(r, &p[i])
	}
	min, max := solve(g, rg, p)
	fmt.Println(min, max)
}

func solve(g, rg [][]int, p []int) (int, int) {
	k := len(p)
	d := dijkstra(rg, p[k-1])
	var min, max int
	for i := 0; i < k-1; i++ {
		if d[p[i]] != d[p[i+1]]+1 {
			min++
		}
		for _, v := range g[p[i]] {
			if v != p[i+1] && d[p[i]] == d[v]+1 {
				max++
				break
			}
		}
	}
	return min, max
}

func dijkstra(g [][]int, src int) []int {
	n := len(g)
	d := make([]int, n)
	for i := 0; i < n; i++ {
		d[i] = -1
	}
	d[src] = 0
	q := []int{src}
	for len(q) > 0 {
		cur := q[0]
		q = q[1:]
		for _, v := range g[cur] {
			if d[v] == -1 {
				d[v] = d[cur] + 1
				q = append(q, v)
			}
		}
	}
	return d
}

package main

import (
	"bufio"
	"fmt"
	"os"
	"strconv"
	"sync"
)

type Edge struct {
	to   int
	next int
}

var edge [200005 * 2] Edge
var head [200005] int
var edge1 [200005 * 2] Edge
var head1 [200005] int
var ans, cnt, cnt1, t, mi, ma int
var q [200005]int
var a [200005] int
var vis [200005] int
var dis [200005] int

func add(u, v int) {
	cnt++
	edge[cnt].to = v
	edge[cnt].next = head[u]
	head[u] = cnt
}
func add1(u, v int) {
	cnt1++
	edge1[cnt1].to = v
	edge1[cnt1].next = head1[u]
	head1[u] = cnt1
}
func bfs(s int, n int) {
	for i := 1; i <= n+1; i++ {
		dis[i] = 0x3f3f3f3f
		vis[i] = 0
	}
	t = 0
	dis[s] = 0
	vis[s] = 1
	q[t] = s;
	t++
	for i := 0; i < t; i++ {
		u := q[i]
		for j := head[u]; j != 0; j = edge[j].next {
			v := edge[j].to
			if dis[v] > dis[u]+1 {
				dis[v] = dis[u] + 1
				q[t] = v
				t++
			}
		}
	}
}
func main() {
	n := ReadInt()
	m := ReadInt()
	for i := 1; i <= m; i++ {
		u := ReadInt()
		v := ReadInt()
		add(v, u)
		add1(u, v)
	}
	k := ReadInt()
	for i := 1; i <= k; i++ {
		a[i] = ReadInt()
	}
	bfs(a[k], n)
	for i := 2; i <= k; i++ {
		if dis[a[i]] != dis[a[i-1]]-1 {
			mi++
			ma++
		} else {
			var cnt3 int = 0
			for j := head1[a[i-1]]; j != 0; j = edge1[j].next {
				if dis[edge1[j].to] == dis[a[i-1]]-1 {
					cnt3++
				}
			}
			if cnt3 >= 2 {
				ma++
			}
		}
	}
	fmt.Println(mi, ma)
}

////////////////////////////////////

func max(a, b int64) int64 {
	if a > b {
		return a
	}
	return b
}
func min(a, b int) int {
	if a < b {
		return a
	}
	return b
}

var out chan string
var in *bufio.Scanner
var outWg *sync.WaitGroup

func ReadString() string {
	in.Scan()
	return in.Text()
}
func ReadStringSlice(n int) []string {
	s := make([]string, n)
	for i := 0; i < n; i++ {
		s[i] = ReadString()
	}
	return s
}
func ReadInt() int {
	intStr := ReadString()
	i, _ := strconv.ParseInt(intStr, 10, 32)
	return int(i)
}
func ReadIntSlice(n int) []int {
	arr := make([]int, n)
	for i := 0; i < n; i++ {
		arr[i] = ReadInt()
	}
	return arr
}
func init() {
	//set input
	in = bufio.NewScanner(os.Stdin)
	in.Buffer(make([]byte, 1024), int(2e+5))
	in.Split(bufio.ScanWords)

	//set output
	out = make(chan string, 16)
	outWg = &sync.WaitGroup{}
	outWg.Add(1)

	writer := bufio.NewWriterSize(os.Stdout, int(2e+5))
	go func(write *bufio.Writer) {
		defer outWg.Done()
		defer write.Flush()

		for line := range out {
			write.WriteString(line + "\n")
		}
	}(writer)
}

package main

import (
	"bufio"
	"fmt"
	"io"
	"os"
	"strconv"
)

var reader io.Reader
var scanner *bufio.Scanner

func Init(io io.Reader, max_token_size int) {
	reader = bufio.NewReader(io)
	scanner = bufio.NewScanner(reader)
	// max token size
	scanner.Split(bufio.ScanWords)
	scanner.Buffer([]byte{}, max_token_size)
}

func stderr(v ...interface{}) {
	fmt.Fprintln(os.Stderr, v...)
}

func die(v ...interface{}) {
	fmt.Fprintln(os.Stderr, v...)
	os.Exit(1)
}

func NextInt() int {
	bytes := NextBytes()
	i, err := Atoi(bytes)
	if err != nil {
		die(err)
	}
	return i
}

func NextBytes() []byte {
	if !scanner.Scan() {
		die(scanner.Err())
	}
	bytes := scanner.Bytes()
	copied := make([]byte, len(bytes))
	copy(copied, bytes)
	return copied
}

func Atoi(b []byte) (int, error) {
	neg := false
	if b[0] == '+' {
		b = b[1:]
	} else if b[0] == '-' {
		neg = true
		b = b[1:]
	}
	n := 0
	for _, v := range b {
		if v < '0' || v > '9' {
			return 0, strconv.ErrSyntax
		}
		n = n*10 + int(v-'0')
	}
	if neg {
		return -n, nil
	}
	return n, nil
}

func ExtendByteArray(a []byte, size int) []byte {
	if size <= len(a) {
		return a
	} else {
		return append(a, make([]byte, size-len(a))...)
	}
}

func ExtendIntArray(a []int, size int) []int {
	if size <= len(a) {
		return a
	} else {
		return append(a, make([]int, size-len(a))...)
	}
}

type Graph struct {
	n     int
	m     int
	edges int
	fst   []int
	nxt   []int
	end   []int
}

func (g *Graph) Add(a, b int) {
	g.nxt[g.edges] = g.fst[a]
	g.fst[a] = g.edges
	g.end[g.edges] = b
	g.edges++
}

func (g *Graph) Adjacent0(a int, fn func(b int)) {
	for u := g.fst[a]; u != -1; u = g.nxt[u] {
		if u%2 == 0 {
			fn(g.end[u])
		}
	}
}

func (g *Graph) Adjacent1(a int, fn func(b int)) {
	for u := g.fst[a]; u != -1; u = g.nxt[u] {
		if u%2 == 1 {
			fn(g.end[u])
		}
	}
}

func NewGraph(n, m int) *Graph {
	g := &Graph{n, m, 0, make([]int, n), make([]int, m), make([]int, m)}
	for i := 0; i < n; i++ {
		g.fst[i] = -1
	}
	return g
}

func main() {
	inf := os.Stdin
	out := bufio.NewWriter(os.Stdout)
	defer out.Flush()
	// inf, err := os.Open("a.in")
	// if err != nil {
	// 	die(err)
	// }
	// out, err := os.Create("a.out")
	// if err != nil {
	// 	die(err)
	// }
	// defer out.Close()
	Init(inf, 1000010)
	n, m := NextInt(), NextInt()
	g := NewGraph(n, 2*m)
	for i := 0; i < m; i++ {
		u, v := NextInt()-1, NextInt()-1
		g.Add(u, v)
		g.Add(v, u)
	}

	k := NextInt()
	p := make([]int, k)
	for i := 0; i < k; i++ {
		p[i] = NextInt() - 1
	}

	q := make([]int, n)
	was := make([]bool, n)
	d := make([]int, n)
	qh, qt := 0, 0
	q[qt] = p[k-1]
	was[p[k-1]] = true
	qt++
	for qh < qt {
		v := q[qh]
		qh++
		g.Adjacent1(v, func(to int) {
			if !was[to] {
				d[to] = d[v] + 1
				was[to] = true
				q[qt] = to
				qt++
			}
		})
	}

	var minValue, maxValue int
	for i := 0; i+1 < k; i++ {
		// stderr("check", i, p[i]+1, p[i+1]+1, d[p[i]], d[p[i+1]])
		if d[p[i]] != d[p[i+1]]+1 {

			minValue++
			maxValue++
		} else {
			found := false
			g.Adjacent0(p[i], func(to int) {
				if to != p[i+1] && d[p[i]] == d[to]+1 {
					found = true
				}
			})
			if found {
				maxValue++
			}
		}
	}
	fmt.Fprintln(out, minValue, maxValue)
}

package main

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

func main() {
	r := bufio.NewReader(os.Stdin)

	var n, m int
	fmt.Fscanf(r, "%d %d\n", &n, &m)

	g := make(map[int][]int)
	rev := make(map[int][]int)
	for i := 0; i < m; i++ {
		var u, v int
		fmt.Fscanf(r, "%d %d\n", &u, &v)
		g[u] = append(g[u], v)
		rev[v] = append(rev[v], u)
	}

	var k int
	fmt.Fscanf(r, "%d\n", &k)

	p := make([]int, k)
	for i := 0; i < k; i++ {
		fmt.Fscanf(r, "%d", &p[i])
	}

	dist := bfs(rev, p[k-1])

	mini, maxi := 0, 0
	for i, u := range p {
		if i == k-2 {
			break
		}

		nxt := p[i+1]
		if dist[nxt] == dist[u]-1 {
			cc := 0
			for _, v := range g[u] {
				if dist[v] == dist[nxt] {
					cc++
				}
			}
			if cc > 1 {
				maxi++
			}
		} else {
			mini++
			maxi++
		}
	}

	fmt.Printf("%d %d\n", mini, maxi)
}

func bfs(g map[int][]int, s int) map[int]int {
	seen := make(map[int]bool)
	dist := make(map[int]int)

	var q []int

	q = append(q, s)
	dist[s] = 0
	seen[s] = true

	for len(q) > 0 {
		u := q[0]
		q = q[1:]

		for _, v := range g[u] {
			if !seen[v] {
				seen[v] = true
				dist[v] = 1 + dist[u]
				q = append(q, v)
			}
		}
	}

	return dist
}

package main

import (
	"bufio"
	. "fmt"
	"io"
	"os"
)

// github.com/EndlessCheng/codeforces-go
func CF1321D(_r io.Reader, _w io.Writer) {
	in := bufio.NewReader(_r)
	out := bufio.NewWriter(_w)
	defer out.Flush()

	var n, m, v, w, k, min, ex int
	Fscan(in, &n, &m)
	g := make([][]int, n)
	rg := make([][]int, n)
	for ; m > 0; m-- {
		Fscan(in, &v, &w)
		v--
		w--
		g[v] = append(g[v], w)
		rg[w] = append(rg[w], v)
	}
	Fscan(in, &k)
	path := make([]int, k)
	for i := range path {
		Fscan(in, &path[i])
		path[i]--
	}

	dep := make([]int, n)
	vis := make([]bool, n)
	vis[path[k-1]] = true
	q := []int{path[k-1]}
	for len(q) > 0 {
		v, q = q[0], q[1:]
		for _, w := range rg[v] {
			if !vis[w] {
				vis[w] = true
				dep[w] = dep[v] + 1
				q = append(q, w)
			}
		}
	}

	for i, v := range path[:k-1] {
		next := path[i+1]
		if dep[v] <= dep[next] {
			min++
			continue
		}
		for _, w := range g[v] {
			if w != next && dep[w] == dep[next] {
				ex++
				break
			}
		}
	}
	Fprint(out, min, min+ex)
}

func main() { CF1321D(os.Stdin, os.Stdout) }

package main

import (
	"bufio"
	. "fmt"
	"io"
	"os"
)

// github.com/EndlessCheng/codeforces-go
func CF1321D(_r io.Reader, _w io.Writer) {
	in := bufio.NewScanner(_r)
	in.Split(bufio.ScanWords)
	out := bufio.NewWriter(_w)
	defer out.Flush()
	read := func() (x int) {
		in.Scan()
		for _, b := range in.Bytes() {
			x = x*10 + int(b-'0')
		}
		return
	}

	n, m := read(), read()
	g := make([][]int, n)
	rg := make([][]int, n)
	for ; m > 0; m-- {
		v, w := read()-1, read()-1
		g[v] = append(g[v], w)
		rg[w] = append(rg[w], v)
	}
	k := read()
	path := make([]int, k)
	for i := range path {
		path[i] = read() - 1
	}

	dep := make([]int, n)
	vis := make([]bool, n)
	vis[path[k-1]] = true
	q := []int{path[k-1]}
	for len(q) > 0 {
		var v int
		v, q = q[0], q[1:]
		for _, w := range rg[v] {
			if !vis[w] {
				vis[w] = true
				dep[w] = dep[v] + 1
				q = append(q, w)
			}
		}
	}

	min, ex := 0, 0
	for i, v := range path[:k-1] {
		next := path[i+1]
		if dep[v] <= dep[next] {
			min++
			continue
		}
		for _, w := range g[v] {
			if w != next && dep[w] == dep[next] {
				ex++
				break
			}
		}
	}
	Fprint(out, min, min+ex)
}

func main() { CF1321D(os.Stdin, os.Stdout) }

/*
URL:
https://codeforces.com/problemset/problem/1320/B
*/

package main

import (
	"bufio"
	"container/heap"
	"errors"
	"fmt"
	"io"
	"math"
	"os"
	"strconv"
)

/********** FAU standard libraries **********/

//fmt.Sprintf("%b\n", 255) 	// binary expression

/********** I/O usage **********/

//str := ReadString()
//i := ReadInt()
//X := ReadIntSlice(n)
//S := ReadRuneSlice()
//a := ReadFloat64()
//A := ReadFloat64Slice(n)

//str := ZeroPaddingRuneSlice(num, 32)
//str := PrintIntsLine(X...)

/*******************************************************************/

const (
	// General purpose
	MOD          = 1000000000 + 7
	ALPHABET_NUM = 26
	INF_INT64    = math.MaxInt64
	INF_BIT60    = 1 << 60
	INF_INT32    = math.MaxInt32
	INF_BIT30    = 1 << 30
	NIL          = -1

	// for dijkstra, prim, and so on
	WHITE = 0
	GRAY  = 1
	BLACK = 2
)

func init() {
	// bufio.ScanWords <---> bufio.ScanLines
	ReadString = newReadString(os.Stdin, bufio.ScanWords)
	stdout = bufio.NewWriter(os.Stdout)
}

var (
	n, m int
	k    int
	P    []int

	G  [200000 + 50][]Edge
	RG [200000 + 50][]Edge

	cnts [200000 + 50]int
)

func main() {
	n, m = ReadInt2()
	for i := 0; i < m; i++ {
		u, v := ReadInt2()
		u--
		v--

		// 逆向きに貼る
		G[v] = append(G[v], Edge{to: u, cost: 1})
		RG[u] = append(RG[u], Edge{to: v, cost: 1})
	}
	k = ReadInt()
	P = ReadIntSlice(k)
	for i := 0; i < k; i++ {
		P[i]--
	}

	dp, _ := dijkstra(P[k-1], n, G[:n])
	PrintfDebug("dp: %v\n", dp)

	for i := 0; i < n; i++ {
		cnts[dp[i]]++
	}

	mini, maxi := 0, 0
	for i := 0; i < k-1; i++ {
		cid, nid := P[i], P[i+1]

		if dp[cid]-1 < dp[nid] {
			mini++
			maxi++
			continue
		}

		ok := false
		for _, e := range RG[cid] {
			if dp[cid] == dp[e.to]+1 && e.to != nid {
				ok = true
				break
			}
		}
		if ok {
			maxi++
		}
	}

	fmt.Println(mini, maxi)
}

type (
	Edge struct {
		to   int
		cost int
	}
	Vertex struct {
		pri int
		id  int
	}
)

const INF_DIJK = 1 << 30

func dijkstra(sid, n int, AG [][]Edge) (dp, parents []int) {
	dp = make([]int, n)
	parents = make([]int, n)
	colors := make([]int, n)
	for i := 0; i < n; i++ {
		dp[i] = INF_DIJK
		colors[i], parents[i] = WHITE, -1
	}

	temp := make(VertexPQ, 0, 100000+5)
	pq := &temp
	heap.Init(pq)
	heap.Push(pq, &Vertex{pri: 0, id: sid})
	dp[sid] = 0
	colors[sid] = GRAY

	for pq.Len() > 0 {
		pop := heap.Pop(pq).(*Vertex)

		colors[pop.id] = BLACK

		if pop.pri > dp[pop.id] {
			continue
		}

		for _, e := range AG[pop.id] {
			if colors[e.to] == BLACK {
				continue
			}

			if dp[e.to] > dp[pop.id]+e.cost {
				dp[e.to] = dp[pop.id] + e.cost
				heap.Push(pq, &Vertex{pri: dp[e.to], id: e.to})
				colors[e.to], parents[e.to] = GRAY, pop.id
			}
		}
	}

	return dp, parents
}

type VertexPQ []*Vertex

func (pq VertexPQ) Len() int           { return len(pq) }
func (pq VertexPQ) Less(i, j int) bool { return pq[i].pri < pq[j].pri } // <: ASC, >: DESC
func (pq VertexPQ) Swap(i, j int) {
	pq[i], pq[j] = pq[j], pq[i]
}
func (pq *VertexPQ) Push(x interface{}) {
	item := x.(*Vertex)
	*pq = append(*pq, item)
}
func (pq *VertexPQ) Pop() interface{} {
	old := *pq
	n := len(old)
	item := old[n-1]
	*pq = old[0 : n-1]
	return item
}

// how to use
// temp := make(VertexPQ, 0, 100000+1)
// pq := &temp
// heap.Init(pq)
// heap.Push(pq, &Vertex{pri: intValue})
// popped := heap.Pop(pq).(*Vertex)

/*******************************************************************/

/*********** I/O ***********/

var (
	// ReadString returns a WORD string.
	ReadString func() string
	stdout     *bufio.Writer
)

func newReadString(ior io.Reader, sf bufio.SplitFunc) func() string {
	r := bufio.NewScanner(ior)
	r.Buffer(make([]byte, 1024), int(1e+9)) // for Codeforces
	r.Split(sf)

	return func() string {
		if !r.Scan() {
			panic("Scan failed")
		}
		return r.Text()
	}
}

// ReadInt returns an integer.
func ReadInt() int {
	return int(readInt64())
}
func ReadInt2() (int, int) {
	return int(readInt64()), int(readInt64())
}
func ReadInt3() (int, int, int) {
	return int(readInt64()), int(readInt64()), int(readInt64())
}
func ReadInt4() (int, int, int, int) {
	return int(readInt64()), int(readInt64()), int(readInt64()), int(readInt64())
}

// ReadInt64 returns as integer as int64.
func ReadInt64() int64 {
	return readInt64()
}
func ReadInt64_2() (int64, int64) {
	return readInt64(), readInt64()
}
func ReadInt64_3() (int64, int64, int64) {
	return readInt64(), readInt64(), readInt64()
}
func ReadInt64_4() (int64, int64, int64, int64) {
	return readInt64(), readInt64(), readInt64(), readInt64()
}

func readInt64() int64 {
	i, err := strconv.ParseInt(ReadString(), 0, 64)
	if err != nil {
		panic(err.Error())
	}
	return i
}

// ReadIntSlice returns an integer slice that has n integers.
func ReadIntSlice(n int) []int {
	b := make([]int, n)
	for i := 0; i < n; i++ {
		b[i] = ReadInt()
	}
	return b
}

// ReadInt64Slice returns as int64 slice that has n integers.
func ReadInt64Slice(n int) []int64 {
	b := make([]int64, n)
	for i := 0; i < n; i++ {
		b[i] = ReadInt64()
	}
	return b
}

// ReadFloat64 returns an float64.
func ReadFloat64() float64 {
	return float64(readFloat64())
}

func readFloat64() float64 {
	f, err := strconv.ParseFloat(ReadString(), 64)
	if err != nil {
		panic(err.Error())
	}
	return f
}

// ReadFloatSlice returns an float64 slice that has n float64.
func ReadFloat64Slice(n int) []float64 {
	b := make([]float64, n)
	for i := 0; i < n; i++ {
		b[i] = ReadFloat64()
	}
	return b
}

// ReadRuneSlice returns a rune slice.
func ReadRuneSlice() []rune {
	return []rune(ReadString())
}

/*********** Debugging ***********/

// ZeroPaddingRuneSlice returns binary expressions of integer n with zero padding.
// For debugging use.
func ZeroPaddingRuneSlice(n, digitsNum int) []rune {
	sn := fmt.Sprintf("%b", n)

	residualLength := digitsNum - len(sn)
	if residualLength <= 0 {
		return []rune(sn)
	}

	zeros := make([]rune, residualLength)
	for i := 0; i < len(zeros); i++ {
		zeros[i] = '0'
	}

	res := []rune{}
	res = append(res, zeros...)
	res = append(res, []rune(sn)...)

	return res
}

// Strtoi is a wrapper of strconv.Atoi().
// If strconv.Atoi() returns an error, Strtoi calls panic.
func Strtoi(s string) int {
	if i, err := strconv.Atoi(s); err != nil {
		panic(errors.New("[argument error]: Strtoi only accepts integer string"))
	} else {
		return i
	}
}

// PrintIntsLine returns integers string delimited by a space.
func PrintIntsLine(A ...int) string {
	res := []rune{}

	for i := 0; i < len(A); i++ {
		str := strconv.Itoa(A[i])
		res = append(res, []rune(str)...)

		if i != len(A)-1 {
			res = append(res, ' ')
		}
	}

	return string(res)
}

// PrintIntsLine returns integers string delimited by a space.
func PrintInts64Line(A ...int64) string {
	res := []rune{}

	for i := 0; i < len(A); i++ {
		str := strconv.FormatInt(A[i], 10) // 64bit int version
		res = append(res, []rune(str)...)

		if i != len(A)-1 {
			res = append(res, ' ')
		}
	}

	return string(res)
}

// PrintfDebug is wrapper of fmt.Fprintf(os.Stderr, format, a...)
func PrintfDebug(format string, a ...interface{}) {
	fmt.Fprintf(os.Stderr, format, a...)
}

// PrintfBufStdout is function for output strings to buffered os.Stdout.
// You may have to call stdout.Flush() finally.
func PrintfBufStdout(format string, a ...interface{}) {
	fmt.Fprintf(stdout, format, a...)
}

/*
URL:
https://codeforces.com/problemset/problem/1320/B
*/

package main

import (
	"bufio"
	"errors"
	"fmt"
	"io"
	"math"
	"os"
	"strconv"
)

/********** FAU standard libraries **********/

//fmt.Sprintf("%b\n", 255) 	// binary expression

/********** I/O usage **********/

//str := ReadString()
//i := ReadInt()
//X := ReadIntSlice(n)
//S := ReadRuneSlice()
//a := ReadFloat64()
//A := ReadFloat64Slice(n)

//str := ZeroPaddingRuneSlice(num, 32)
//str := PrintIntsLine(X...)

/*******************************************************************/

const (
	// General purpose
	MOD          = 1000000000 + 7
	ALPHABET_NUM = 26
	INF_INT64    = math.MaxInt64
	INF_BIT60    = 1 << 60
	INF_INT32    = math.MaxInt32
	INF_BIT30    = 1 << 30
	NIL          = -1

	// for dijkstra, prim, and so on
	WHITE = 0
	GRAY  = 1
	BLACK = 2
)

func init() {
	// bufio.ScanWords <---> bufio.ScanLines
	ReadString = newReadString(os.Stdin, bufio.ScanWords)
	stdout = bufio.NewWriter(os.Stdout)
}

var (
	n, m int
	k    int
	P    []int

	// G  [200000 + 50][]Edge
	// RG [200000 + 50][]Edge
	G  [200000 + 50][]int
	RG [200000 + 50][]int

	cnts [200000 + 50]int
)

func main() {
	n, m = ReadInt2()
	for i := 0; i < m; i++ {
		u, v := ReadInt2()
		u--
		v--

		// 逆向きに貼る
		// G[v] = append(G[v], Edge{to: u, cost: 1})
		// RG[u] = append(RG[u], Edge{to: v, cost: 1})

		G[v] = append(G[v], u)
		RG[u] = append(RG[u], v)
	}
	k = ReadInt()
	P = ReadIntSlice(k)
	for i := 0; i < k; i++ {
		P[i]--
	}

	// dp, _ := dijkstra(P[k-1], n, G[:n])
	dp, _ := SSSPByBFS(P[k-1], n, G[:n])
	PrintfDebug("dp: %v\n", dp)

	for i := 0; i < n; i++ {
		cnts[dp[i]]++
	}

	mini, maxi := 0, 0
	for i := 0; i < k-1; i++ {
		cid, nid := P[i], P[i+1]

		if dp[cid]-1 < dp[nid] {
			mini++
			maxi++
			continue
		}

		ok := false
		for _, e := range RG[cid] {
			// if dp[cid] == dp[e.to]+1 && e.to != nid {
			// 	ok = true
			// 	break
			// }
			if dp[cid] == dp[e]+1 && e != nid {
				ok = true
				break
			}
		}
		if ok {
			maxi++
		}
	}

	fmt.Println(mini, maxi)
}

func SSSPByBFS(sid, n int, AG [][]int) (dp []int, visited []bool) {
	dp = make([]int, n)
	visited = make([]bool, n)

	for i := 0; i < n; i++ {
		dp[i] = INF_BIT30
		visited[i] = false
	}

	Q := []Node{}
	dp[sid] = 0
	visited[sid] = true
	Q = append(Q, Node{id: sid, cost: dp[sid]})

	for len(Q) > 0 {
		cnode := Q[0]
		Q = Q[1:]

		for _, nid := range G[cnode.id] {
			// 訪問済みならパス
			if visited[nid] {
				continue
			}

			dp[nid] = cnode.cost + 1
			visited[nid] = true
			Q = append(Q, Node{id: nid, cost: dp[nid]})
		}
	}

	return dp, visited
}

type Node struct {
	id, cost int
}

/*******************************************************************/

/*********** I/O ***********/

var (
	// ReadString returns a WORD string.
	ReadString func() string
	stdout     *bufio.Writer
)

func newReadString(ior io.Reader, sf bufio.SplitFunc) func() string {
	r := bufio.NewScanner(ior)
	r.Buffer(make([]byte, 1024), int(1e+9)) // for Codeforces
	r.Split(sf)

	return func() string {
		if !r.Scan() {
			panic("Scan failed")
		}
		return r.Text()
	}
}

// ReadInt returns an integer.
func ReadInt() int {
	return int(readInt64())
}
func ReadInt2() (int, int) {
	return int(readInt64()), int(readInt64())
}
func ReadInt3() (int, int, int) {
	return int(readInt64()), int(readInt64()), int(readInt64())
}
func ReadInt4() (int, int, int, int) {
	return int(readInt64()), int(readInt64()), int(readInt64()), int(readInt64())
}

// ReadInt64 returns as integer as int64.
func ReadInt64() int64 {
	return readInt64()
}
func ReadInt64_2() (int64, int64) {
	return readInt64(), readInt64()
}
func ReadInt64_3() (int64, int64, int64) {
	return readInt64(), readInt64(), readInt64()
}
func ReadInt64_4() (int64, int64, int64, int64) {
	return readInt64(), readInt64(), readInt64(), readInt64()
}

func readInt64() int64 {
	i, err := strconv.ParseInt(ReadString(), 0, 64)
	if err != nil {
		panic(err.Error())
	}
	return i
}

// ReadIntSlice returns an integer slice that has n integers.
func ReadIntSlice(n int) []int {
	b := make([]int, n)
	for i := 0; i < n; i++ {
		b[i] = ReadInt()
	}
	return b
}

// ReadInt64Slice returns as int64 slice that has n integers.
func ReadInt64Slice(n int) []int64 {
	b := make([]int64, n)
	for i := 0; i < n; i++ {
		b[i] = ReadInt64()
	}
	return b
}

// ReadFloat64 returns an float64.
func ReadFloat64() float64 {
	return float64(readFloat64())
}

func readFloat64() float64 {
	f, err := strconv.ParseFloat(ReadString(), 64)
	if err != nil {
		panic(err.Error())
	}
	return f
}

// ReadFloatSlice returns an float64 slice that has n float64.
func ReadFloat64Slice(n int) []float64 {
	b := make([]float64, n)
	for i := 0; i < n; i++ {
		b[i] = ReadFloat64()
	}
	return b
}

// ReadRuneSlice returns a rune slice.
func ReadRuneSlice() []rune {
	return []rune(ReadString())
}

/*********** Debugging ***********/

// ZeroPaddingRuneSlice returns binary expressions of integer n with zero padding.
// For debugging use.
func ZeroPaddingRuneSlice(n, digitsNum int) []rune {
	sn := fmt.Sprintf("%b", n)

	residualLength := digitsNum - len(sn)
	if residualLength <= 0 {
		return []rune(sn)
	}

	zeros := make([]rune, residualLength)
	for i := 0; i < len(zeros); i++ {
		zeros[i] = '0'
	}

	res := []rune{}
	res = append(res, zeros...)
	res = append(res, []rune(sn)...)

	return res
}

// Strtoi is a wrapper of strconv.Atoi().
// If strconv.Atoi() returns an error, Strtoi calls panic.
func Strtoi(s string) int {
	if i, err := strconv.Atoi(s); err != nil {
		panic(errors.New("[argument error]: Strtoi only accepts integer string"))
	} else {
		return i
	}
}

// PrintIntsLine returns integers string delimited by a space.
func PrintIntsLine(A ...int) string {
	res := []rune{}

	for i := 0; i < len(A); i++ {
		str := strconv.Itoa(A[i])
		res = append(res, []rune(str)...)

		if i != len(A)-1 {
			res = append(res, ' ')
		}
	}

	return string(res)
}

// PrintIntsLine returns integers string delimited by a space.
func PrintInts64Line(A ...int64) string {
	res := []rune{}

	for i := 0; i < len(A); i++ {
		str := strconv.FormatInt(A[i], 10) // 64bit int version
		res = append(res, []rune(str)...)

		if i != len(A)-1 {
			res = append(res, ' ')
		}
	}

	return string(res)
}

// PrintfDebug is wrapper of fmt.Fprintf(os.Stderr, format, a...)
func PrintfDebug(format string, a ...interface{}) {
	fmt.Fprintf(os.Stderr, format, a...)
}

// PrintfBufStdout is function for output strings to buffered os.Stdout.
// You may have to call stdout.Flush() finally.
func PrintfBufStdout(format string, a ...interface{}) {
	fmt.Fprintf(stdout, format, a...)
}

/*
URL:
https://codeforces.com/problemset/problem/1320/B
*/

package main

import (
	"bufio"
	"container/heap"
	"errors"
	"fmt"
	"io"
	"math"
	"os"
	"strconv"
)

/********** FAU standard libraries **********/

//fmt.Sprintf("%b\n", 255) 	// binary expression

/********** I/O usage **********/

//str := ReadString()
//i := ReadInt()
//X := ReadIntSlice(n)
//S := ReadRuneSlice()
//a := ReadFloat64()
//A := ReadFloat64Slice(n)

//str := ZeroPaddingRuneSlice(num, 32)
//str := PrintIntsLine(X...)

/*******************************************************************/

const (
	// General purpose
	MOD          = 1000000000 + 7
	ALPHABET_NUM = 26
	INF_INT64    = math.MaxInt64
	INF_BIT60    = 1 << 60
	INF_INT32    = math.MaxInt32
	INF_BIT30    = 1 << 30
	NIL          = -1

	// for dijkstra, prim, and so on
	WHITE = 0
	GRAY  = 1
	BLACK = 2
)

func init() {
	// bufio.ScanWords <---> bufio.ScanLines
	ReadString = newReadString(os.Stdin, bufio.ScanWords)
	stdout = bufio.NewWriter(os.Stdout)
}

var (
	n, m int
	k    int
	P    []int

	G [200000 + 50][]Edge

	cnts [200000 + 50]int
)

func main() {
	n, m = ReadInt2()
	for i := 0; i < m; i++ {
		u, v := ReadInt2()
		u--
		v--

		// 逆向きに貼る
		G[v] = append(G[v], Edge{to: u, cost: 1})
	}
	k = ReadInt()
	P = ReadIntSlice(k)
	for i := 0; i < k; i++ {
		P[i]--
	}

	dp, _ := dijkstra(P[k-1], n, G[:n])
	PrintfDebug("dp: %v\n", dp)

	for i := 0; i < n; i++ {
		cnts[dp[i]]++
	}

	mini, maxi := 0, 0
	for i := 0; i < k-1; i++ {
		cid, nid := P[i], P[i+1]
		A := dp[cid] == dp[nid]+1
		cnt := cnts[dp[cid]-1]
		if A {
			cnt--
		}
		B := cnt > 0

		if A && B {
			maxi++
		} else if A && !B {
		} else if !A && B {
			mini++
			maxi++
		}
	}

	fmt.Println(mini, maxi)
}

type (
	Edge struct {
		to   int
		cost int
	}
	Vertex struct {
		pri int
		id  int
	}
)

const INF_DIJK = 1 << 30

func dijkstra(sid, n int, AG [][]Edge) (dp, parents []int) {
	dp = make([]int, n)
	parents = make([]int, n)
	colors := make([]int, n)
	for i := 0; i < n; i++ {
		dp[i] = INF_DIJK
		colors[i], parents[i] = WHITE, -1
	}

	temp := make(VertexPQ, 0, 100000+5)
	pq := &temp
	heap.Init(pq)
	heap.Push(pq, &Vertex{pri: 0, id: sid})
	dp[sid] = 0
	colors[sid] = GRAY

	for pq.Len() > 0 {
		pop := heap.Pop(pq).(*Vertex)

		colors[pop.id] = BLACK

		if pop.pri > dp[pop.id] {
			continue
		}

		for _, e := range AG[pop.id] {
			if colors[e.to] == BLACK {
				continue
			}

			if dp[e.to] > dp[pop.id]+e.cost {
				dp[e.to] = dp[pop.id] + e.cost
				heap.Push(pq, &Vertex{pri: dp[e.to], id: e.to})
				colors[e.to], parents[e.to] = GRAY, pop.id
			}
		}
	}

	return dp, parents
}

type VertexPQ []*Vertex

func (pq VertexPQ) Len() int           { return len(pq) }
func (pq VertexPQ) Less(i, j int) bool { return pq[i].pri < pq[j].pri } // <: ASC, >: DESC
func (pq VertexPQ) Swap(i, j int) {
	pq[i], pq[j] = pq[j], pq[i]
}
func (pq *VertexPQ) Push(x interface{}) {
	item := x.(*Vertex)
	*pq = append(*pq, item)
}
func (pq *VertexPQ) Pop() interface{} {
	old := *pq
	n := len(old)
	item := old[n-1]
	*pq = old[0 : n-1]
	return item
}

// how to use
// temp := make(VertexPQ, 0, 100000+1)
// pq := &temp
// heap.Init(pq)
// heap.Push(pq, &Vertex{pri: intValue})
// popped := heap.Pop(pq).(*Vertex)

/*******************************************************************/

/*********** I/O ***********/

var (
	// ReadString returns a WORD string.
	ReadString func() string
	stdout     *bufio.Writer
)

func newReadString(ior io.Reader, sf bufio.SplitFunc) func() string {
	r := bufio.NewScanner(ior)
	r.Buffer(make([]byte, 1024), int(1e+9)) // for Codeforces
	r.Split(sf)

	return func() string {
		if !r.Scan() {
			panic("Scan failed")
		}
		return r.Text()
	}
}

// ReadInt returns an integer.
func ReadInt() int {
	return int(readInt64())
}
func ReadInt2() (int, int) {
	return int(readInt64()), int(readInt64())
}
func ReadInt3() (int, int, int) {
	return int(readInt64()), int(readInt64()), int(readInt64())
}
func ReadInt4() (int, int, int, int) {
	return int(readInt64()), int(readInt64()), int(readInt64()), int(readInt64())
}

// ReadInt64 returns as integer as int64.
func ReadInt64() int64 {
	return readInt64()
}
func ReadInt64_2() (int64, int64) {
	return readInt64(), readInt64()
}
func ReadInt64_3() (int64, int64, int64) {
	return readInt64(), readInt64(), readInt64()
}
func ReadInt64_4() (int64, int64, int64, int64) {
	return readInt64(), readInt64(), readInt64(), readInt64()
}

func readInt64() int64 {
	i, err := strconv.ParseInt(ReadString(), 0, 64)
	if err != nil {
		panic(err.Error())
	}
	return i
}

// ReadIntSlice returns an integer slice that has n integers.
func ReadIntSlice(n int) []int {
	b := make([]int, n)
	for i := 0; i < n; i++ {
		b[i] = ReadInt()
	}
	return b
}

// ReadInt64Slice returns as int64 slice that has n integers.
func ReadInt64Slice(n int) []int64 {
	b := make([]int64, n)
	for i := 0; i < n; i++ {
		b[i] = ReadInt64()
	}
	return b
}

// ReadFloat64 returns an float64.
func ReadFloat64() float64 {
	return float64(readFloat64())
}

func readFloat64() float64 {
	f, err := strconv.ParseFloat(ReadString(), 64)
	if err != nil {
		panic(err.Error())
	}
	return f
}

// ReadFloatSlice returns an float64 slice that has n float64.
func ReadFloat64Slice(n int) []float64 {
	b := make([]float64, n)
	for i := 0; i < n; i++ {
		b[i] = ReadFloat64()
	}
	return b
}

// ReadRuneSlice returns a rune slice.
func ReadRuneSlice() []rune {
	return []rune(ReadString())
}

/*********** Debugging ***********/

// ZeroPaddingRuneSlice returns binary expressions of integer n with zero padding.
// For debugging use.
func ZeroPaddingRuneSlice(n, digitsNum int) []rune {
	sn := fmt.Sprintf("%b", n)

	residualLength := digitsNum - len(sn)
	if residualLength <= 0 {
		return []rune(sn)
	}

	zeros := make([]rune, residualLength)
	for i := 0; i < len(zeros); i++ {
		zeros[i] = '0'
	}

	res := []rune{}
	res = append(res, zeros...)
	res = append(res, []rune(sn)...)

	return res
}

// Strtoi is a wrapper of strconv.Atoi().
// If strconv.Atoi() returns an error, Strtoi calls panic.
func Strtoi(s string) int {
	if i, err := strconv.Atoi(s); err != nil {
		panic(errors.New("[argument error]: Strtoi only accepts integer string"))
	} else {
		return i
	}
}

// PrintIntsLine returns integers string delimited by a space.
func PrintIntsLine(A ...int) string {
	res := []rune{}

	for i := 0; i < len(A); i++ {
		str := strconv.Itoa(A[i])
		res = append(res, []rune(str)...)

		if i != len(A)-1 {
			res = append(res, ' ')
		}
	}

	return string(res)
}

// PrintIntsLine returns integers string delimited by a space.
func PrintInts64Line(A ...int64) string {
	res := []rune{}

	for i := 0; i < len(A); i++ {
		str := strconv.FormatInt(A[i], 10) // 64bit int version
		res = append(res, []rune(str)...)

		if i != len(A)-1 {
			res = append(res, ' ')
		}
	}

	return string(res)
}

// PrintfDebug is wrapper of fmt.Fprintf(os.Stderr, format, a...)
func PrintfDebug(format string, a ...interface{}) {
	fmt.Fprintf(os.Stderr, format, a...)
}

// PrintfBufStdout is function for output strings to buffered os.Stdout.
// You may have to call stdout.Flush() finally.
func PrintfBufStdout(format string, a ...interface{}) {
	fmt.Fprintf(stdout, format, a...)
}

/*
URL:
https://codeforces.com/problemset/problem/1320/B
*/

package main

import (
	"bufio"
	"container/heap"
	"errors"
	"fmt"
	"io"
	"math"
	"os"
	"strconv"
)

/********** FAU standard libraries **********/

//fmt.Sprintf("%b\n", 255) 	// binary expression

/********** I/O usage **********/

//str := ReadString()
//i := ReadInt()
//X := ReadIntSlice(n)
//S := ReadRuneSlice()
//a := ReadFloat64()
//A := ReadFloat64Slice(n)

//str := ZeroPaddingRuneSlice(num, 32)
//str := PrintIntsLine(X...)

/*******************************************************************/

const (
	// General purpose
	MOD          = 1000000000 + 7
	ALPHABET_NUM = 26
	INF_INT64    = math.MaxInt64
	INF_BIT60    = 1 << 60
	INF_INT32    = math.MaxInt32
	INF_BIT30    = 1 << 30
	NIL          = -1

	// for dijkstra, prim, and so on
	WHITE = 0
	GRAY  = 1
	BLACK = 2
)

func init() {
	// bufio.ScanWords <---> bufio.ScanLines
	ReadString = newReadString(os.Stdin, bufio.ScanWords)
	stdout = bufio.NewWriter(os.Stdout)
}

var (
	n, m int
	k    int
	P    []int

	G [200000 + 50][]Edge

	cnts [200000 + 50]int
)

func main() {
	n, m = ReadInt2()
	for i := 0; i < m; i++ {
		u, v := ReadInt2()
		u--
		v--

		// 逆向きに貼る
		G[v] = append(G[v], Edge{to: u, cost: 1})
	}
	k = ReadInt()
	P = ReadIntSlice(k)
	for i := 0; i < k; i++ {
		P[i]--
	}

	dp, _ := dijkstra(P[k-1], n, G[:n])
	PrintfDebug("dp: %v\n", dp)

	for i := 0; i < n; i++ {
		cnts[dp[i]]++
	}

	mini, maxi := 0, 0
	for i := 0; i < k-1; i++ {
		cid, nid := P[i], P[i+1]

		A := dp[cid] == dp[nid]+1

		cnt := cnts[dp[cid]-1]
		// if A {
		// 	cnt--
		// }
		cnt--
		B := cnt > 0

		if A && B {
			maxi++
		} else if A && !B {
		} else if !A && B {
			mini++
			maxi++
		}
	}

	fmt.Println(mini, maxi)
}

type (
	Edge struct {
		to   int
		cost int
	}
	Vertex struct {
		pri int
		id  int
	}
)

const INF_DIJK = 1 << 30

func dijkstra(sid, n int, AG [][]Edge) (dp, parents []int) {
	dp = make([]int, n)
	parents = make([]int, n)
	colors := make([]int, n)
	for i := 0; i < n; i++ {
		dp[i] = INF_DIJK
		colors[i], parents[i] = WHITE, -1
	}

	temp := make(VertexPQ, 0, 100000+5)
	pq := &temp
	heap.Init(pq)
	heap.Push(pq, &Vertex{pri: 0, id: sid})
	dp[sid] = 0
	colors[sid] = GRAY

	for pq.Len() > 0 {
		pop := heap.Pop(pq).(*Vertex)

		colors[pop.id] = BLACK

		if pop.pri > dp[pop.id] {
			continue
		}

		for _, e := range AG[pop.id] {
			if colors[e.to] == BLACK {
				continue
			}

			if dp[e.to] > dp[pop.id]+e.cost {
				dp[e.to] = dp[pop.id] + e.cost
				heap.Push(pq, &Vertex{pri: dp[e.to], id: e.to})
				colors[e.to], parents[e.to] = GRAY, pop.id
			}
		}
	}

	return dp, parents
}

type VertexPQ []*Vertex

func (pq VertexPQ) Len() int           { return len(pq) }
func (pq VertexPQ) Less(i, j int) bool { return pq[i].pri < pq[j].pri } // <: ASC, >: DESC
func (pq VertexPQ) Swap(i, j int) {
	pq[i], pq[j] = pq[j], pq[i]
}
func (pq *VertexPQ) Push(x interface{}) {
	item := x.(*Vertex)
	*pq = append(*pq, item)
}
func (pq *VertexPQ) Pop() interface{} {
	old := *pq
	n := len(old)
	item := old[n-1]
	*pq = old[0 : n-1]
	return item
}

// how to use
// temp := make(VertexPQ, 0, 100000+1)
// pq := &temp
// heap.Init(pq)
// heap.Push(pq, &Vertex{pri: intValue})
// popped := heap.Pop(pq).(*Vertex)

/*******************************************************************/

/*********** I/O ***********/

var (
	// ReadString returns a WORD string.
	ReadString func() string
	stdout     *bufio.Writer
)

func newReadString(ior io.Reader, sf bufio.SplitFunc) func() string {
	r := bufio.NewScanner(ior)
	r.Buffer(make([]byte, 1024), int(1e+9)) // for Codeforces
	r.Split(sf)

	return func() string {
		if !r.Scan() {
			panic("Scan failed")
		}
		return r.Text()
	}
}

// ReadInt returns an integer.
func ReadInt() int {
	return int(readInt64())
}
func ReadInt2() (int, int) {
	return int(readInt64()), int(readInt64())
}
func ReadInt3() (int, int, int) {
	return int(readInt64()), int(readInt64()), int(readInt64())
}
func ReadInt4() (int, int, int, int) {
	return int(readInt64()), int(readInt64()), int(readInt64()), int(readInt64())
}

// ReadInt64 returns as integer as int64.
func ReadInt64() int64 {
	return readInt64()
}
func ReadInt64_2() (int64, int64) {
	return readInt64(), readInt64()
}
func ReadInt64_3() (int64, int64, int64) {
	return readInt64(), readInt64(), readInt64()
}
func ReadInt64_4() (int64, int64, int64, int64) {
	return readInt64(), readInt64(), readInt64(), readInt64()
}

func readInt64() int64 {
	i, err := strconv.ParseInt(ReadString(), 0, 64)
	if err != nil {
		panic(err.Error())
	}
	return i
}

// ReadIntSlice returns an integer slice that has n integers.
func ReadIntSlice(n int) []int {
	b := make([]int, n)
	for i := 0; i < n; i++ {
		b[i] = ReadInt()
	}
	return b
}

// ReadInt64Slice returns as int64 slice that has n integers.
func ReadInt64Slice(n int) []int64 {
	b := make([]int64, n)
	for i := 0; i < n; i++ {
		b[i] = ReadInt64()
	}
	return b
}

// ReadFloat64 returns an float64.
func ReadFloat64() float64 {
	return float64(readFloat64())
}

func readFloat64() float64 {
	f, err := strconv.ParseFloat(ReadString(), 64)
	if err != nil {
		panic(err.Error())
	}
	return f
}

// ReadFloatSlice returns an float64 slice that has n float64.
func ReadFloat64Slice(n int) []float64 {
	b := make([]float64, n)
	for i := 0; i < n; i++ {
		b[i] = ReadFloat64()
	}
	return b
}

// ReadRuneSlice returns a rune slice.
func ReadRuneSlice() []rune {
	return []rune(ReadString())
}

/*********** Debugging ***********/

// ZeroPaddingRuneSlice returns binary expressions of integer n with zero padding.
// For debugging use.
func ZeroPaddingRuneSlice(n, digitsNum int) []rune {
	sn := fmt.Sprintf("%b", n)

	residualLength := digitsNum - len(sn)
	if residualLength <= 0 {
		return []rune(sn)
	}

	zeros := make([]rune, residualLength)
	for i := 0; i < len(zeros); i++ {
		zeros[i] = '0'
	}

	res := []rune{}
	res = append(res, zeros...)
	res = append(res, []rune(sn)...)

	return res
}

// Strtoi is a wrapper of strconv.Atoi().
// If strconv.Atoi() returns an error, Strtoi calls panic.
func Strtoi(s string) int {
	if i, err := strconv.Atoi(s); err != nil {
		panic(errors.New("[argument error]: Strtoi only accepts integer string"))
	} else {
		return i
	}
}

// PrintIntsLine returns integers string delimited by a space.
func PrintIntsLine(A ...int) string {
	res := []rune{}

	for i := 0; i < len(A); i++ {
		str := strconv.Itoa(A[i])
		res = append(res, []rune(str)...)

		if i != len(A)-1 {
			res = append(res, ' ')
		}
	}

	return string(res)
}

// PrintIntsLine returns integers string delimited by a space.
func PrintInts64Line(A ...int64) string {
	res := []rune{}

	for i := 0; i < len(A); i++ {
		str := strconv.FormatInt(A[i], 10) // 64bit int version
		res = append(res, []rune(str)...)

		if i != len(A)-1 {
			res = append(res, ' ')
		}
	}

	return string(res)
}

// PrintfDebug is wrapper of fmt.Fprintf(os.Stderr, format, a...)
func PrintfDebug(format string, a ...interface{}) {
	fmt.Fprintf(os.Stderr, format, a...)
}

// PrintfBufStdout is function for output strings to buffered os.Stdout.
// You may have to call stdout.Flush() finally.
func PrintfBufStdout(format string, a ...interface{}) {
	fmt.Fprintf(stdout, format, a...)
}

/*
URL:
https://codeforces.com/problemset/problem/1320/B
*/

package main

import (
	"bufio"
	"container/heap"
	"errors"
	"fmt"
	"io"
	"math"
	"os"
	"strconv"
)

/********** FAU standard libraries **********/

//fmt.Sprintf("%b\n", 255) 	// binary expression

/********** I/O usage **********/

//str := ReadString()
//i := ReadInt()
//X := ReadIntSlice(n)
//S := ReadRuneSlice()
//a := ReadFloat64()
//A := ReadFloat64Slice(n)

//str := ZeroPaddingRuneSlice(num, 32)
//str := PrintIntsLine(X...)

/*******************************************************************/

const (
	// General purpose
	MOD          = 1000000000 + 7
	ALPHABET_NUM = 26
	INF_INT64    = math.MaxInt64
	INF_BIT60    = 1 << 60
	INF_INT32    = math.MaxInt32
	INF_BIT30    = 1 << 30
	NIL          = -1

	// for dijkstra, prim, and so on
	WHITE = 0
	GRAY  = 1
	BLACK = 2
)

func init() {
	// bufio.ScanWords <---> bufio.ScanLines
	ReadString = newReadString(os.Stdin, bufio.ScanWords)
	stdout = bufio.NewWriter(os.Stdout)
}

var (
	n, m int
	k    int
	P    []int

	G [200000 + 50][]Edge

	cnts [200000 + 50]int
)

func main() {
	n, m = ReadInt2()
	for i := 0; i < m; i++ {
		u, v := ReadInt2()
		u--
		v--

		// 逆向きに貼る
		G[v] = append(G[v], Edge{to: u, cost: 1})
	}
	k = ReadInt()
	P = ReadIntSlice(k)
	for i := 0; i < k; i++ {
		P[i]--
	}

	dp, _ := dijkstra(P[k-1], n, G[:n])
	PrintfDebug("dp: %v\n", dp)

	for i := 0; i < n; i++ {
		cnts[dp[i]]++
	}

	mini, maxi := 0, 0
	for i := 0; i < k-1; i++ {
		cid, nid := P[i], P[i+1]

		// A := dp[cid] == dp[nid]+1

		// cnt := cnts[dp[cid]-1]
		// if A {
		// 	cnt--
		// }
		// B := cnt > 0

		// if A && B {
		// 	maxi++
		// } else if A && !B {
		// } else if !A && B {
		// 	mini++
		// 	maxi++
		// }

		// by tutorial...
		if dp[cid]-1 < dp[nid] {
			mini++
			maxi++
			continue
		}

		A := dp[cid] == dp[nid]+1
		cnt := cnts[dp[cid]-1]
		if A {
			cnt--
		}
		B := cnt > 0
		if A && B {
			maxi++
		}
	}

	fmt.Println(mini, maxi)
}

type (
	Edge struct {
		to   int
		cost int
	}
	Vertex struct {
		pri int
		id  int
	}
)

const INF_DIJK = 1 << 30

func dijkstra(sid, n int, AG [][]Edge) (dp, parents []int) {
	dp = make([]int, n)
	parents = make([]int, n)
	colors := make([]int, n)
	for i := 0; i < n; i++ {
		dp[i] = INF_DIJK
		colors[i], parents[i] = WHITE, -1
	}

	temp := make(VertexPQ, 0, 100000+5)
	pq := &temp
	heap.Init(pq)
	heap.Push(pq, &Vertex{pri: 0, id: sid})
	dp[sid] = 0
	colors[sid] = GRAY

	for pq.Len() > 0 {
		pop := heap.Pop(pq).(*Vertex)

		colors[pop.id] = BLACK

		if pop.pri > dp[pop.id] {
			continue
		}

		for _, e := range AG[pop.id] {
			if colors[e.to] == BLACK {
				continue
			}

			if dp[e.to] > dp[pop.id]+e.cost {
				dp[e.to] = dp[pop.id] + e.cost
				heap.Push(pq, &Vertex{pri: dp[e.to], id: e.to})
				colors[e.to], parents[e.to] = GRAY, pop.id
			}
		}
	}

	return dp, parents
}

type VertexPQ []*Vertex

func (pq VertexPQ) Len() int           { return len(pq) }
func (pq VertexPQ) Less(i, j int) bool { return pq[i].pri < pq[j].pri } // <: ASC, >: DESC
func (pq VertexPQ) Swap(i, j int) {
	pq[i], pq[j] = pq[j], pq[i]
}
func (pq *VertexPQ) Push(x interface{}) {
	item := x.(*Vertex)
	*pq = append(*pq, item)
}
func (pq *VertexPQ) Pop() interface{} {
	old := *pq
	n := len(old)
	item := old[n-1]
	*pq = old[0 : n-1]
	return item
}

// how to use
// temp := make(VertexPQ, 0, 100000+1)
// pq := &temp
// heap.Init(pq)
// heap.Push(pq, &Vertex{pri: intValue})
// popped := heap.Pop(pq).(*Vertex)

/*******************************************************************/

/*********** I/O ***********/

var (
	// ReadString returns a WORD string.
	ReadString func() string
	stdout     *bufio.Writer
)

func newReadString(ior io.Reader, sf bufio.SplitFunc) func() string {
	r := bufio.NewScanner(ior)
	r.Buffer(make([]byte, 1024), int(1e+9)) // for Codeforces
	r.Split(sf)

	return func() string {
		if !r.Scan() {
			panic("Scan failed")
		}
		return r.Text()
	}
}

// ReadInt returns an integer.
func ReadInt() int {
	return int(readInt64())
}
func ReadInt2() (int, int) {
	return int(readInt64()), int(readInt64())
}
func ReadInt3() (int, int, int) {
	return int(readInt64()), int(readInt64()), int(readInt64())
}
func ReadInt4() (int, int, int, int) {
	return int(readInt64()), int(readInt64()), int(readInt64()), int(readInt64())
}

// ReadInt64 returns as integer as int64.
func ReadInt64() int64 {
	return readInt64()
}
func ReadInt64_2() (int64, int64) {
	return readInt64(), readInt64()
}
func ReadInt64_3() (int64, int64, int64) {
	return readInt64(), readInt64(), readInt64()
}
func ReadInt64_4() (int64, int64, int64, int64) {
	return readInt64(), readInt64(), readInt64(), readInt64()
}

func readInt64() int64 {
	i, err := strconv.ParseInt(ReadString(), 0, 64)
	if err != nil {
		panic(err.Error())
	}
	return i
}

// ReadIntSlice returns an integer slice that has n integers.
func ReadIntSlice(n int) []int {
	b := make([]int, n)
	for i := 0; i < n; i++ {
		b[i] = ReadInt()
	}
	return b
}

// ReadInt64Slice returns as int64 slice that has n integers.
func ReadInt64Slice(n int) []int64 {
	b := make([]int64, n)
	for i := 0; i < n; i++ {
		b[i] = ReadInt64()
	}
	return b
}

// ReadFloat64 returns an float64.
func ReadFloat64() float64 {
	return float64(readFloat64())
}

func readFloat64() float64 {
	f, err := strconv.ParseFloat(ReadString(), 64)
	if err != nil {
		panic(err.Error())
	}
	return f
}

// ReadFloatSlice returns an float64 slice that has n float64.
func ReadFloat64Slice(n int) []float64 {
	b := make([]float64, n)
	for i := 0; i < n; i++ {
		b[i] = ReadFloat64()
	}
	return b
}

// ReadRuneSlice returns a rune slice.
func ReadRuneSlice() []rune {
	return []rune(ReadString())
}

/*********** Debugging ***********/

// ZeroPaddingRuneSlice returns binary expressions of integer n with zero padding.
// For debugging use.
func ZeroPaddingRuneSlice(n, digitsNum int) []rune {
	sn := fmt.Sprintf("%b", n)

	residualLength := digitsNum - len(sn)
	if residualLength <= 0 {
		return []rune(sn)
	}

	zeros := make([]rune, residualLength)
	for i := 0; i < len(zeros); i++ {
		zeros[i] = '0'
	}

	res := []rune{}
	res = append(res, zeros...)
	res = append(res, []rune(sn)...)

	return res
}

// Strtoi is a wrapper of strconv.Atoi().
// If strconv.Atoi() returns an error, Strtoi calls panic.
func Strtoi(s string) int {
	if i, err := strconv.Atoi(s); err != nil {
		panic(errors.New("[argument error]: Strtoi only accepts integer string"))
	} else {
		return i
	}
}

// PrintIntsLine returns integers string delimited by a space.
func PrintIntsLine(A ...int) string {
	res := []rune{}

	for i := 0; i < len(A); i++ {
		str := strconv.Itoa(A[i])
		res = append(res, []rune(str)...)

		if i != len(A)-1 {
			res = append(res, ' ')
		}
	}

	return string(res)
}

// PrintIntsLine returns integers string delimited by a space.
func PrintInts64Line(A ...int64) string {
	res := []rune{}

	for i := 0; i < len(A); i++ {
		str := strconv.FormatInt(A[i], 10) // 64bit int version
		res = append(res, []rune(str)...)

		if i != len(A)-1 {
			res = append(res, ' ')
		}
	}

	return string(res)
}

// PrintfDebug is wrapper of fmt.Fprintf(os.Stderr, format, a...)
func PrintfDebug(format string, a ...interface{}) {
	fmt.Fprintf(os.Stderr, format, a...)
}

// PrintfBufStdout is function for output strings to buffered os.Stdout.
// You may have to call stdout.Flush() finally.
func PrintfBufStdout(format string, a ...interface{}) {
	fmt.Fprintf(stdout, format, a...)
}

/*
URL:
https://codeforces.com/problemset/problem/1320/B
*/

package main

import (
	"bufio"
	"container/heap"
	"errors"
	"fmt"
	"io"
	"math"
	"os"
	"strconv"
)

/********** FAU standard libraries **********/

//fmt.Sprintf("%b\n", 255) 	// binary expression

/********** I/O usage **********/

//str := ReadString()
//i := ReadInt()
//X := ReadIntSlice(n)
//S := ReadRuneSlice()
//a := ReadFloat64()
//A := ReadFloat64Slice(n)

//str := ZeroPaddingRuneSlice(num, 32)
//str := PrintIntsLine(X...)

/*******************************************************************/

const (
	// General purpose
	MOD          = 1000000000 + 7
	ALPHABET_NUM = 26
	INF_INT64    = math.MaxInt64
	INF_BIT60    = 1 << 60
	INF_INT32    = math.MaxInt32
	INF_BIT30    = 1 << 30
	NIL          = -1

	// for dijkstra, prim, and so on
	WHITE = 0
	GRAY  = 1
	BLACK = 2
)

func init() {
	// bufio.ScanWords <---> bufio.ScanLines
	ReadString = newReadString(os.Stdin, bufio.ScanWords)
	stdout = bufio.NewWriter(os.Stdout)
}

var (
	n, m int
	k    int
	P    []int

	G [200000 + 50][]Edge

	cnts [200000 + 50]int
)

func main() {
	n, m = ReadInt2()
	for i := 0; i < m; i++ {
		u, v := ReadInt2()
		u--
		v--

		// 逆向きに貼る
		G[v] = append(G[v], Edge{to: u, cost: 1})
	}
	k = ReadInt()
	P = ReadIntSlice(k)
	for i := 0; i < k; i++ {
		P[i]--
	}

	dp, _ := dijkstra(P[k-1], n, G[:n])
	PrintfDebug("dp: %v\n", dp)

	for i := 0; i < n; i++ {
		cnts[dp[i]]++
	}

	mini, maxi := 0, 0
	for i := 0; i < k-1; i++ {
		cid, nid := P[i], P[i+1]

		// A := dp[cid] == dp[nid]+1

		// cnt := cnts[dp[cid]-1]
		// if A {
		// 	cnt--
		// }
		// B := cnt > 0

		// if A && B {
		// 	maxi++
		// } else if A && !B {
		// } else if !A && B {
		// 	mini++
		// 	maxi++
		// }

		// by tutorial...
		if dp[cid]-1 < dp[nid] {
			mini++
			maxi++
			continue
		}

		A := dp[cid] == dp[nid]+1
		cnt := cnts[dp[cid]-1]
		if A {
			cnt--
		}
		B := cnt > 0
		if B {
			maxi++
		}
	}

	fmt.Println(mini, maxi)
}

type (
	Edge struct {
		to   int
		cost int
	}
	Vertex struct {
		pri int
		id  int
	}
)

const INF_DIJK = 1 << 30

func dijkstra(sid, n int, AG [][]Edge) (dp, parents []int) {
	dp = make([]int, n)
	parents = make([]int, n)
	colors := make([]int, n)
	for i := 0; i < n; i++ {
		dp[i] = INF_DIJK
		colors[i], parents[i] = WHITE, -1
	}

	temp := make(VertexPQ, 0, 100000+5)
	pq := &temp
	heap.Init(pq)
	heap.Push(pq, &Vertex{pri: 0, id: sid})
	dp[sid] = 0
	colors[sid] = GRAY

	for pq.Len() > 0 {
		pop := heap.Pop(pq).(*Vertex)

		colors[pop.id] = BLACK

		if pop.pri > dp[pop.id] {
			continue
		}

		for _, e := range AG[pop.id] {
			if colors[e.to] == BLACK {
				continue
			}

			if dp[e.to] > dp[pop.id]+e.cost {
				dp[e.to] = dp[pop.id] + e.cost
				heap.Push(pq, &Vertex{pri: dp[e.to], id: e.to})
				colors[e.to], parents[e.to] = GRAY, pop.id
			}
		}
	}

	return dp, parents
}

type VertexPQ []*Vertex

func (pq VertexPQ) Len() int           { return len(pq) }
func (pq VertexPQ) Less(i, j int) bool { return pq[i].pri < pq[j].pri } // <: ASC, >: DESC
func (pq VertexPQ) Swap(i, j int) {
	pq[i], pq[j] = pq[j], pq[i]
}
func (pq *VertexPQ) Push(x interface{}) {
	item := x.(*Vertex)
	*pq = append(*pq, item)
}
func (pq *VertexPQ) Pop() interface{} {
	old := *pq
	n := len(old)
	item := old[n-1]
	*pq = old[0 : n-1]
	return item
}

// how to use
// temp := make(VertexPQ, 0, 100000+1)
// pq := &temp
// heap.Init(pq)
// heap.Push(pq, &Vertex{pri: intValue})
// popped := heap.Pop(pq).(*Vertex)

/*******************************************************************/

/*********** I/O ***********/

var (
	// ReadString returns a WORD string.
	ReadString func() string
	stdout     *bufio.Writer
)

func newReadString(ior io.Reader, sf bufio.SplitFunc) func() string {
	r := bufio.NewScanner(ior)
	r.Buffer(make([]byte, 1024), int(1e+9)) // for Codeforces
	r.Split(sf)

	return func() string {
		if !r.Scan() {
			panic("Scan failed")
		}
		return r.Text()
	}
}

// ReadInt returns an integer.
func ReadInt() int {
	return int(readInt64())
}
func ReadInt2() (int, int) {
	return int(readInt64()), int(readInt64())
}
func ReadInt3() (int, int, int) {
	return int(readInt64()), int(readInt64()), int(readInt64())
}
func ReadInt4() (int, int, int, int) {
	return int(readInt64()), int(readInt64()), int(readInt64()), int(readInt64())
}

// ReadInt64 returns as integer as int64.
func ReadInt64() int64 {
	return readInt64()
}
func ReadInt64_2() (int64, int64) {
	return readInt64(), readInt64()
}
func ReadInt64_3() (int64, int64, int64) {
	return readInt64(), readInt64(), readInt64()
}
func ReadInt64_4() (int64, int64, int64, int64) {
	return readInt64(), readInt64(), readInt64(), readInt64()
}

func readInt64() int64 {
	i, err := strconv.ParseInt(ReadString(), 0, 64)
	if err != nil {
		panic(err.Error())
	}
	return i
}

// ReadIntSlice returns an integer slice that has n integers.
func ReadIntSlice(n int) []int {
	b := make([]int, n)
	for i := 0; i < n; i++ {
		b[i] = ReadInt()
	}
	return b
}

// ReadInt64Slice returns as int64 slice that has n integers.
func ReadInt64Slice(n int) []int64 {
	b := make([]int64, n)
	for i := 0; i < n; i++ {
		b[i] = ReadInt64()
	}
	return b
}

// ReadFloat64 returns an float64.
func ReadFloat64() float64 {
	return float64(readFloat64())
}

func readFloat64() float64 {
	f, err := strconv.ParseFloat(ReadString(), 64)
	if err != nil {
		panic(err.Error())
	}
	return f
}

// ReadFloatSlice returns an float64 slice that has n float64.
func ReadFloat64Slice(n int) []float64 {
	b := make([]float64, n)
	for i := 0; i < n; i++ {
		b[i] = ReadFloat64()
	}
	return b
}

// ReadRuneSlice returns a rune slice.
func ReadRuneSlice() []rune {
	return []rune(ReadString())
}

/*********** Debugging ***********/

// ZeroPaddingRuneSlice returns binary expressions of integer n with zero padding.
// For debugging use.
func ZeroPaddingRuneSlice(n, digitsNum int) []rune {
	sn := fmt.Sprintf("%b", n)

	residualLength := digitsNum - len(sn)
	if residualLength <= 0 {
		return []rune(sn)
	}

	zeros := make([]rune, residualLength)
	for i := 0; i < len(zeros); i++ {
		zeros[i] = '0'
	}

	res := []rune{}
	res = append(res, zeros...)
	res = append(res, []rune(sn)...)

	return res
}

// Strtoi is a wrapper of strconv.Atoi().
// If strconv.Atoi() returns an error, Strtoi calls panic.
func Strtoi(s string) int {
	if i, err := strconv.Atoi(s); err != nil {
		panic(errors.New("[argument error]: Strtoi only accepts integer string"))
	} else {
		return i
	}
}

// PrintIntsLine returns integers string delimited by a space.
func PrintIntsLine(A ...int) string {
	res := []rune{}

	for i := 0; i < len(A); i++ {
		str := strconv.Itoa(A[i])
		res = append(res, []rune(str)...)

		if i != len(A)-1 {
			res = append(res, ' ')
		}
	}

	return string(res)
}

// PrintIntsLine returns integers string delimited by a space.
func PrintInts64Line(A ...int64) string {
	res := []rune{}

	for i := 0; i < len(A); i++ {
		str := strconv.FormatInt(A[i], 10) // 64bit int version
		res = append(res, []rune(str)...)

		if i != len(A)-1 {
			res = append(res, ' ')
		}
	}

	return string(res)
}

// PrintfDebug is wrapper of fmt.Fprintf(os.Stderr, format, a...)
func PrintfDebug(format string, a ...interface{}) {
	fmt.Fprintf(os.Stderr, format, a...)
}

// PrintfBufStdout is function for output strings to buffered os.Stdout.
// You may have to call stdout.Flush() finally.
func PrintfBufStdout(format string, a ...interface{}) {
	fmt.Fprintf(stdout, format, a...)
}

package main

import (
	"bufio"
	. "fmt"
	"io"
	"os"
)

func run(_r io.Reader, _w io.Writer) {
	in := bufio.NewReader(_r)
	out := bufio.NewWriter(_w)
	defer out.Flush()

	var n, m, k int
	Fscan(in, &n, &m)
	g := make([][]int, n)
	rg := make([][]int, n)
	for i := 0; i < m; i++ {
		var v, w int
		Fscan(in, &v, &w)
		v--
		w--
		g[v] = append(g[v], w)
		rg[w] = append(rg[w], v)
	}
	Fscan(in, &k)
	path := make([]int, k)
	for i := range path {
		Fscan(in, &path[i])
		path[i]--
	}
	if k == 2 {
		Fprintln(out, 0, 0)
		return
	}
	st, end := path[0], path[k-1]

	// 最小：从终点看，每一步是否离终点更近了 dfswithdepth 相邻dep之差为1
	// 最大：

	vis := make([]bool, n)
	vis[st] = true
	dep := make([]int, n)
	type pair struct{ v, dep int }
	queue := []pair{{st, 0}}
	for len(queue) > 0 {
		var p pair
		p, queue = queue[0], queue[1:]
		dep[p.v] = p.dep
		for _, w := range g[p.v] {
			if !vis[w] {
				vis[w] = true
				queue = append(queue, pair{w, p.dep + 1})
			}
		}
	}

	vis = make([]bool, n)
	vis[end] = true
	rdep := make([]int, n)
	queue = []pair{{end, 0}}
	for len(queue) > 0 {
		var p pair
		p, queue = queue[0], queue[1:]
		rdep[p.v] = p.dep
		for _, w := range rg[p.v] {
			if !vis[w] {
				vis[w] = true
				queue = append(queue, pair{w, p.dep + 1})
			}
		}
	}

	minAns := 0
	for i := 1; i < k; i++ {
		v, last := path[i], path[i-1]
		if rdep[v]-rdep[last] >= 0 {
			minAns++
		}
	}

	maxAns := 0
	for i := 0; i < k-1; i++ {
		v := path[i]
		next := path[i+1]
		if rdep[v]-rdep[next] <= 0 {
			maxAns++
			continue
		}
		for _, w := range g[v] {
			if w != next && dep[w] == dep[next] {
				maxAns++
				continue
			}
		}
	}

	Fprintln(out, minAns, maxAns)
}

func main() { run(os.Stdin, os.Stdout) }

package main

import (
	"bufio"
	. "fmt"
	"io"
	"os"
)

func run(_r io.Reader, _w io.Writer) {
	in := bufio.NewReader(_r)
	out := bufio.NewWriter(_w)
	defer out.Flush()

	var n, m, k int
	Fscan(in, &n, &m)
	g := make([][]int, n)
	rg := make([][]int, n)
	for i := 0; i < m; i++ {
		var v, w int
		Fscan(in, &v, &w)
		v--
		w--
		g[v] = append(g[v], w)
		rg[w] = append(rg[w], v)
	}
	Fscan(in, &k)
	path := make([]int, k)
	for i := range path {
		Fscan(in, &path[i])
		path[i]--
	}
	if k == 2 {
		Fprintln(out, 0, 0)
		return
	}
	st, end := path[0], path[k-1]

	// 最小：从终点看，每一步是否离终点更近了 dfswithdepth 相邻dep之差为1
	// 最大：

	vis := make([]bool, n)
	vis[st] = true
	dep := make([]int, n)
	type pair struct{ v, dep int }
	queue := []pair{{st, 0}}
	for len(queue) > 0 {
		var p pair
		p, queue = queue[0], queue[1:]
		dep[p.v] = p.dep
		for _, w := range g[p.v] {
			if !vis[w] {
				vis[w] = true
				queue = append(queue, pair{w, p.dep + 1})
			}
		}
	}

	vis = make([]bool, n)
	vis[end] = true
	rdep := make([]int, n)
	queue = []pair{{end, 0}}
	for len(queue) > 0 {
		var p pair
		p, queue = queue[0], queue[1:]
		rdep[p.v] = p.dep
		for _, w := range rg[p.v] {
			if !vis[w] {
				vis[w] = true
				queue = append(queue, pair{w, p.dep + 1})
			}
		}
	}

	minAns := 0
	for i := 1; i < k; i++ {
		v, last := path[i], path[i-1]
		if rdep[v]-rdep[last] >= 0 {
			minAns++
		}
	}

	maxAns := 0
	for i := 0; i < k-1; i++ {
		v := path[i]
		next := path[i+1]
		if rdep[v]-rdep[next] <= 0 {
			maxAns++
			continue
		}
		for _, w := range g[v] {
			if w != next && rdep[w] == rdep[next] {
				maxAns++
				continue
			}
		}
	}

	Fprintln(out, minAns, maxAns)
}

func main() { run(os.Stdin, os.Stdout) }

package main

import (
	"bufio"
	. "fmt"
	"io"
	"os"
)

func run(_r io.Reader, _w io.Writer) {
	in := bufio.NewReader(_r)
	out := bufio.NewWriter(_w)
	defer out.Flush()

	var n, m, k int
	Fscan(in, &n, &m)
	g := make([][]int, n)
	rg := make([][]int, n)
	for i := 0; i < m; i++ {
		var v, w int
		Fscan(in, &v, &w)
		v--
		w--
		g[v] = append(g[v], w)
		rg[w] = append(rg[w], v)
	}
	Fscan(in, &k)
	path := make([]int, k)
	for i := range path {
		Fscan(in, &path[i])
		path[i]--
	}
	st, end := path[0], path[k-1]

	// 最小：从终点看，每一步是否离终点更近了 dfswithdepth 相邻dep之差为1
	// 最大：

	vis := make([]bool, n)
	vis[st] = true
	dep := make([]int, n)
	type pair struct{ v, dep int }
	queue := []pair{{st, 0}}
	for len(queue) > 0 {
		var p pair
		p, queue = queue[0], queue[1:]
		dep[p.v] = p.dep
		for _, w := range g[p.v] {
			if !vis[w] {
				vis[w] = true
				queue = append(queue, pair{w, p.dep + 1})
			}
		}
	}

	vis = make([]bool, n)
	vis[end] = true
	rdep := make([]int, n)
	queue = []pair{{end, 0}}
	for len(queue) > 0 {
		var p pair
		p, queue = queue[0], queue[1:]
		rdep[p.v] = p.dep
		for _, w := range rg[p.v] {
			if !vis[w] {
				vis[w] = true
				queue = append(queue, pair{w, p.dep + 1})
			}
		}
	}

	minAns := 0
	for i := 1; i < k; i++ {
		v, last := path[i], path[i-1]
		if rdep[v]-rdep[last] >= 0 {
			minAns++
		}
	}

	maxAns := 0
	for i := 0; i < k-1; i++ {
		v := path[i]
		next := path[i+1]
		if rdep[v]-rdep[next] <= 0 {
			maxAns++
			continue
		}
		for _, w := range g[v] {
			if w != next && dep[w] == dep[next] {
				maxAns++
				break
			}
		}
	}

	Fprintln(out, minAns, maxAns)
}

func main() { run(os.Stdin, os.Stdout) }


package main

import (
	"fmt"
)

var (
	primes = make([]int, 0, 100000)
	composite = make([]bool, 1300000)
)

func main() {
	for i := 2; len(primes) != cap(primes); i++ {
		if !composite[i] {
			primes = append(primes, i)
			for j := i * 2; j < len(composite); j += i {
				composite[j] = true
			}
		}
	}
	var n, k int
	fmt.Scan(&n, &k)
	if n / 2 > k {
		fmt.Println(-1)
		return
	}
	if n == 1 {
		if k == 0 {
			fmt.Println(1)
		} else {
			fmt.Println(-1)
		}
		return
	}
	x := k - (n / 2 - 1)
	fmt.Print(x * 2, x * 3)
	if x == 1 {
		primes = primes[2:]
	}
	for _, p := range primes[:n-2] {
		fmt.Print(" ", p)
	}
	fmt.Println()
}

// 414A-mic
package main

import (
    "fmt"
)

func main() {
    var n, k int
    fmt.Scan(&n, &k)
    t := n/2 - 1
    u := k - t
    if n == 1 {
        if k == 0 {
            fmt.Print("1")
        } else {
            fmt.Print(-1)
        }
        return
    }
    if u < 1 {
        fmt.Print("-1")
        return
    }

    fmt.Print(u)
    fmt.Print(" ")
    fmt.Print(2 * u)
    cou := 1
    for i := 0; i < t; i++ {
        for cou == u || cou+1 == u || cou+1 == 2*u || cou == 2*u {
            cou += 2
        }
        fmt.Print(" ")
        fmt.Print(cou)
        fmt.Print(" ")
        fmt.Print(cou + 1)
        cou += 2
    }
    if n%2 == 1 {
        if cou == u {
            cou++
        }
        if cou == 2*u {
            cou++
        }
        fmt.Print(" ")
        fmt.Print(cou)
    }
    fmt.Println()
}

package main

import (
	"bufio"
	"fmt"
	"os"
	"strconv"
	"strings"
)

type Io struct {
	reader    *bufio.Reader
	writer    *bufio.Writer
	tokens    []string
	nextToken int
}

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

func (io *Io) Flush() {
	err := io.writer.Flush()
	if err != nil {
		panic(err)
	}
}

func (io *Io) NextLine() string {
	var buffer []byte
	for {
		line, isPrefix, err := io.reader.ReadLine()
		if err != nil {
			panic(err)
		}
		buffer = append(buffer, line...)
		if !isPrefix {
			break
		}
	}
	return string(buffer)
}

func (io *Io) Next() string {
	for io.nextToken >= len(io.tokens) {
		line := io.NextLine()
		io.tokens = strings.Fields(line)
		io.nextToken = 0
	}
	r := io.tokens[io.nextToken]
	io.nextToken++
	return r
}

func (io *Io) NextInt() int {
	i, err := strconv.Atoi(io.Next())
	if err != nil {
		panic(err)
	}
	return i
}

func (io *Io) NextLong() int64 {
	i, err := strconv.ParseInt(io.Next(), 10, 64)
	if err != nil {
		panic(err)
	}
	return i
}

func (io *Io) NextDouble() float64 {
	i, err := strconv.ParseFloat(io.Next(), 64)
	if err != nil {
		panic(err)
	}
	return i
}

func (io *Io) PrintLn(a ...interface{}) {
	fmt.Fprintln(io.writer, a...)
}

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

func (io *Io) PrintIntLn(a []int) {
	b := []interface{}{}
	for _, x := range a {
		b = append(b, x)
	}
	io.PrintLn(b...)
}

func (io *Io) PrintStringLn(a []string) {
	b := []interface{}{}
	for _, x := range a {
		b = append(b, x)
	}
	io.PrintLn(b...)
}

func Log(name string, value interface{}) {
	fmt.Fprintf(os.Stderr, "%s=%+v\n", name, value)
}

func intMin(a, b int) int {
	if a < b {
		return a
	}
	return b
}

func main() {
	io := NewIo()
	defer io.Flush()
	N := io.NextInt()
	K := io.NextInt()
	M := N / 2
	if K < M {
		io.PrintLn(-1)
	} else if N == 1 {
		if K == 0 {
			io.PrintLn(1)
		} else {
			io.PrintLn(-1)
		}
	} else {
		A := make([]int, N)
		used := make(map[int]bool)
		//Log("M", M)
		A[0] = K - (M - 1)
		A[1] = 2 * A[0]
		used[A[0]] = true
		used[A[1]] = true
		last := 0
		for i := 0; i < M - 1; i++ {
			for {
				_, ok := used[last + 1]
				_, ok2 := used[last + 2]
				if ok || ok2 {
					last += 2
				} else {
					break
				}
			}
			A[2 + 2 * i] = last + 1
			A[2 + 2 * i + 1] = last + 2
			last = last + 2
		}
		if N % 2 == 1 {
			for {
				_, ok := used[last + 1]
				if ok {
					last++
				} else {
					break
				}
			}
			A[N - 1] = last + 1
		}
		io.PrintIntLn(A)
	}
}

package main
import (
	"fmt"
	//"sort"
	//"unicode/utf8"
)
func main() {
	var n,k int
	fmt.Scan(&n,&k)
	if n==1 && k>0 || k<n/2 {
		fmt.Println("-1")
	} else if n==1 && k==0 {
		fmt.Println("1")
	} else {
		if k==n/2 {
			for i:=1;i<n;i++ {
				fmt.Print(i," ")
			}
			fmt.Println(n)
		} else {
			t:=k-n/2+1
			fmt.Print(t," ",t*2)
			for i:=t*2+1;i<t*2+n-1;i++ {
				fmt.Print(" ",i)
			}
			fmt.Println()
		}
	}

}

package main

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

func main() {
    writer := bufio.NewWriter(os.Stdout)
    var n,k int
    fmt.Scan(&n,&k)
    if (n/2 > k) || ((n < 2) && (k > 0)) {
        writer.WriteString("-1\n")
    } else if k == 0 {
        writer.WriteString("1\n")
    } else if (n/2) == k {
        for i := 1; i <= n; i++ {
            writer.WriteString(strconv.Itoa(i))
            if i == n { writer.WriteRune('\n') } else { writer.WriteRune(' ') }
        }
    } else {
        a := k-((n/2)-1)
        writer.WriteString(strconv.Itoa(a)+" "+strconv.Itoa(a*2))
        for i := 1; i <= (n-2); i++ {
            writer.WriteString(" "+strconv.Itoa(i+200000000))
        }
        writer.WriteRune('\n')
    }
    writer.Flush()
}

package main

import (
	"fmt"
)

func main() {
	var n, k int
	fmt.Scan(&n, &k)
	if n / 2 > k {
		fmt.Println(-1)
		return
	}
	x := k - (n / 2 - 1)
	fmt.Print(x, x)
	for i := 2; i < n; i++ {
		fmt.Print(" ", 1)
	}
	fmt.Println()
}

package main
import (
	"fmt"
	//"sort"
	//"unicode/utf8"
)
func main() {
	var n,k int
	fmt.Scan(&n,&k)
	hit:=n/2
	if hit==0 && k==0 {
		fmt.Print("1")
	} else if hit>k || hit==0 {
		fmt.Print("-1")
	} else {
		x:=k-(hit-1)
		fmt.Print(x," ",x*k)
		x=x*k+1
		n=n-2
		for j:=0;j<n;j++ {
			fmt.Print(" ",x)
			x++
		}
		fmt.Print("")
	}

}

package main

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

func main() {
    writer := bufio.NewWriter(os.Stdout)
    var n,k int
    fmt.Scan(&n,&k)
    if (n/2 > k) || ((n < 2) && (k > 0)) {
        writer.WriteString("-1\n")
    } else if k == 0 {
        writer.WriteString("1\n")
    } else if (n/2) == k {
        for i := 1; i <= n; i++ {
            writer.WriteString(strconv.Itoa(i))
            if i == n { writer.WriteRune('\n') } else { writer.WriteRune(' ') }
        }
    } else {
        a := k-((n/2)-1)
        writer.WriteString(strconv.Itoa(a)+" "+strconv.Itoa(a*2))
        for i := 1; i <= (n-2); i++ {
            writer.WriteString(" "+strconv.Itoa(i+100000000))
        }
        writer.WriteRune('\n')
    }
    writer.Flush()
}