← Home
```go
package main

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

func abs(x int) int {
	if x < 0 {
		return -x
	}
	return x
}

const MOD = 1000000007
const MAX = 1000005

var (
	parent  = make([]int, MAX)
	vCount  = make([]int, MAX)
	eCount  = make([]int, MAX)
	hasLoop = make([]bool, MAX)
	active  = make([]bool, MAX)
)

func Find(i int) int {
	root := i
	for parent[root] != root {
		root = parent[root]
	}
	curr := i
	for curr != root {
		nxt := parent[curr]
		parent[curr] = root
		curr = nxt
	}
	return root
}

func AddEdge(u, v int) {
	active[u] = true
	active[v] = true
	rootU := Find(u)
	rootV := Find(v)
	if rootU != rootV {
		parent[rootU] = rootV
		vCount[rootV] += vCount[rootU]
		eCount[rootV] += eCount[rootU] + 1
		hasLoop[rootV] = hasLoop[rootV] || hasLoop[rootU]
	} else {
		eCount[rootU]++
		if u == v {
			hasLoop[rootU] = true
		}
	}
}

func nextInt(reader *bufio.Reader) int {
	res := 0
	for {
		c, err := reader.ReadByte()
		if err != nil {
			return 0
		}
		if c >= '0' && c <= '9' {
			res = int(c - '0')
			break
		}
	}
	for {
		c, err := reader.ReadByte()
		if err != nil || c < '0' || c > '9' {
			break
		}
		res = res*10 + int(c - '0')
	}
	return res
}

func main() {
	reader := bufio.NewReader(os.Stdin)
	writer := bufio.NewWriter(os.Stdout)
	defer writer.Flush()

	t := nextInt(reader)
	for tc := 0; tc < t; tc++ {
		n := nextInt(reader)
		m := nextInt(reader)
		k := nextInt(reader)

		sz := n * m
		for i := 0; i < sz; i++ {
			parent[i] = i
			vCount[i] = 1
			eCount[i] = 0
			hasLoop[i] = false
			active[i] = false
		}

		prevX := nextInt(reader)
		prevY := nextInt(reader)

		possible := true

		for i := 0; i < k; i++ {
			currX := nextInt(reader)
			currY := nextInt(reader)

			if !possible {
				prevX, prevY = currX, currY
				continue
			}

			dx := abs(prevX - currX)
			dy := abs(prevY - currY)

			if dx+dy != 2 {
				possible = false
			} else {
				if dx == 1 && dy == 1 {
					u := (prevX-1)*m + (currY - 1)
					v := (currX-1)*m + (prevY - 1)
					AddEdge(u, v)
				} else if dx == 2 {
					midX := (prevX + currX) / 2
					u := (midX-1)*m + (prevY - 1)
					AddEdge(u, u)
				} else if dy == 2 {
					midY := (prevY + currY) / 2
					u := (prevX-1)*m + (midY - 1)
					AddEdge(u, u)
				}
			}

			prevX, prevY = currX, currY
		}

		if !possible {
			fmt.Fprintln(writer, 0)
			continue
		}

		ans := int64(1)
		for i := 0; i < sz; i++ {
			if active[i] && parent[i] == i {
				V := vCount[i]
				E := eCount[i]

				if E > V {
					ans = 0
					break
				} else if E == V {
					if hasLoop[i] {
						ans = (ans * 1) % MOD
					} else {
						ans = (ans * 2) % MOD
					}
				} else if E == V-1 {
					ans = (ans * int64(V)) % MOD
				}
			}
		}

		fmt.Fprintln(writer, ans)
	}
}
```