using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;

namespace Codeforces
{
	internal class Template
	{
		private void Solve()
		{
			var n = cin.NextInt();
			var m = cin.NextInt();
			var k = cin.NextInt();
			var points = new HashSet<Point>();
			for (var i = 0; i < k; i++)
			{
				var point = new Point(cin.NextInt(), cin.NextInt());
				points.Add(point);
			}
			var r = points.GroupBy(x => x.Y).ToDictionary(x => x.Key, x => x.ToList());
			var c = points.GroupBy(x => x.X).ToDictionary(x => x.Key, x => x.ToList());
			var queue = new PriorityQueue<int, Point>();
			queue.Enqueue(0, new Point(1, 1));
			var visited = new HashSet<Point>();
			var dx = new []{-1, 0, 0, 1};
			var dy = new[] {0, 1, -1, 0};
			var end = new Point(n, m);
			var ans = int.MaxValue;
			while (queue.Any())
			{
				var front = queue.Dequeue();
				var dist = front.Key;
				if (ans <= dist)
				{
					Console.WriteLine(ans);
					return;
				}
				var point = front.Value;
				if (visited.Contains(front.Value))
				{
					continue;
				}
				if (front.Value.Equals(end))
				{
					Console.WriteLine(dist);
					return;
				}
				visited.Add(front.Value);
				for (var i = 0; i < dx.Length; i++)
				{
					var x = point.X + dx[i];
					var y = point.Y + dy[i];
					var p = new Point(y, x);
					if (x >= 1 && x <= m && y >= 1 && y <= n && points.Contains(p))
					{
						queue.Enqueue(dist, p);
					}
				}
				for (var i = -2; i <= 2; i++)
				{
					var x = point.X + i;
					if (x == m && Math.Abs(i) <= 1)
					{
						ans = Math.Min(ans, dist + 1);
					}
					if (c.ContainsKey(x))
					{
						foreach (var p in c[x])
						{
							if (!visited.Contains(p))
							{
								queue.Enqueue(dist + 1, p);
							}
						}
					}
					var y = point.Y + i;
					if (y == n && Math.Abs(i) <= 1)
					{
						ans = Math.Min(ans, dist + 1);
					}
					if (r.ContainsKey(y))
					{
						foreach (var p in r[y])
						{
							if (!visited.Contains(p))
							{
								queue.Enqueue(dist + 1, p);
							}
						}
					}
				}
			}
			if (ans < int.MaxValue)
			{
				Console.WriteLine(ans);
			}
			else
			{
				Console.WriteLine(-1);
			}
		}

		public class Point
		{
			public int X, Y;

			public Point(int y, int x)
			{
				X = x;
				Y = y;
			}

			public override int GetHashCode()
			{
				return X * 10001 + Y;
			}

			public override bool Equals(object obj)
			{
				var other = (Point) obj;
				return X == other.X && Y == other.Y;
			}
		}

		public class PriorityQueue<TPriority, TValue> : ICollection<KeyValuePair<TPriority, TValue>>
		{
			private readonly List<KeyValuePair<TPriority, TValue>> baseHeap;
			private readonly IComparer<TPriority> comparer;

			public PriorityQueue()
				: this(Comparer<TPriority>.Default)
			{
			}

			public PriorityQueue(int capacity)
				: this(capacity, Comparer<TPriority>.Default)
			{
			}

			public PriorityQueue(int capacity, IComparer<TPriority> comparer)
			{
				if (comparer == null)
					throw new ArgumentNullException();

				baseHeap = new List<KeyValuePair<TPriority, TValue>>(capacity);
				this.comparer = comparer;
			}

			public PriorityQueue(IComparer<TPriority> comparer)
			{
				if (comparer == null)
					throw new ArgumentNullException();

				baseHeap = new List<KeyValuePair<TPriority, TValue>>();
				this.comparer = comparer;
			}

			public PriorityQueue(IEnumerable<KeyValuePair<TPriority, TValue>> data)
				: this(data, Comparer<TPriority>.Default)
			{
			}

			public PriorityQueue(IEnumerable<KeyValuePair<TPriority, TValue>> data, IComparer<TPriority> comparer)
			{
				if (data == null || comparer == null)
					throw new ArgumentNullException();

				this.comparer = comparer;
				baseHeap = new List<KeyValuePair<TPriority, TValue>>(data);
				// heapify data
				for (int pos = baseHeap.Count / 2 - 1; pos >= 0; pos--)
					HeapifyFromBeginningToEnd(pos);
			}

			public static PriorityQueue<TPriority, TValue> MergeQueues(PriorityQueue<TPriority, TValue> pq1, PriorityQueue<TPriority, TValue> pq2)
			{
				if (pq1 == null || pq2 == null)
					throw new ArgumentNullException();
				// ReSharper disable once PossibleUnintendedReferenceComparison
				if (pq1.comparer != pq2.comparer)
					throw new InvalidOperationException("Priority queues to be merged must have equal comparers");
				return MergeQueues(pq1, pq2, pq1.comparer);
			}

			public static PriorityQueue<TPriority, TValue> MergeQueues(PriorityQueue<TPriority, TValue> pq1, PriorityQueue<TPriority, TValue> pq2, IComparer<TPriority> comparer)
			{
				if (pq1 == null || pq2 == null || comparer == null)
					throw new ArgumentNullException();
				// merge data
				PriorityQueue<TPriority, TValue> result = new PriorityQueue<TPriority, TValue>(pq1.Count + pq2.Count, pq1.comparer);
				result.baseHeap.AddRange(pq1.baseHeap);
				result.baseHeap.AddRange(pq2.baseHeap);
				// heapify data
				for (int pos = result.baseHeap.Count / 2 - 1; pos >= 0; pos--)
					result.HeapifyFromBeginningToEnd(pos);

				return result;
			}

			public void Enqueue(TPriority priority, TValue value)
			{
				Insert(priority, value);
			}

			public KeyValuePair<TPriority, TValue> Dequeue()
			{
				if (!IsEmpty)
				{
					KeyValuePair<TPriority, TValue> result = baseHeap[0];
					DeleteRoot();
					return result;
				}
				else
					throw new InvalidOperationException("Priority queue is empty");
			}

			public TValue DequeueValue()
			{
				return Dequeue().Value;
			}

			public KeyValuePair<TPriority, TValue> Peek()
			{
				if (!IsEmpty)
					return baseHeap[0];
				else
					throw new InvalidOperationException("Priority queue is empty");
			}

			public TValue PeekValue()
			{
				return Peek().Value;
			}

			public bool IsEmpty
			{
				get { return baseHeap.Count == 0; }
			}

			private void ExchangeElements(int pos1, int pos2)
			{
				KeyValuePair<TPriority, TValue> val = baseHeap[pos1];
				baseHeap[pos1] = baseHeap[pos2];
				baseHeap[pos2] = val;
			}

			private void Insert(TPriority priority, TValue value)
			{
				KeyValuePair<TPriority, TValue> val = new KeyValuePair<TPriority, TValue>(priority, value);
				baseHeap.Add(val);

				// heap[i] have children heap[2*i + 1] and heap[2*i + 2] and parent heap[(i-1)/ 2];

				// heapify after insert, from end to beginning
				HeapifyFromEndToBeginning(baseHeap.Count - 1);
			}

			private int HeapifyFromEndToBeginning(int pos)
			{
				if (pos >= baseHeap.Count) return -1;

				while (pos > 0)
				{
					int parentPos = (pos - 1) / 2;
					if (comparer.Compare(baseHeap[parentPos].Key, baseHeap[pos].Key) > 0)
					{
						ExchangeElements(parentPos, pos);
						pos = parentPos;
					}
					else break;
				}
				return pos;
			}

			private void DeleteRoot()
			{
				if (baseHeap.Count <= 1)
				{
					baseHeap.Clear();
					return;
				}

				baseHeap[0] = baseHeap[baseHeap.Count - 1];
				baseHeap.RemoveAt(baseHeap.Count - 1);

				// heapify
				HeapifyFromBeginningToEnd(0);
			}

			private void HeapifyFromBeginningToEnd(int pos)
			{
				if (pos >= baseHeap.Count) return;

				// heap[i] have children heap[2*i + 1] and heap[2*i + 2] and parent heap[(i-1)/ 2];

				while (true)
				{
					// on each iteration exchange element with its smallest child
					int smallest = pos;
					int left = 2 * pos + 1;
					int right = 2 * pos + 2;
					if (left < baseHeap.Count && comparer.Compare(baseHeap[smallest].Key, baseHeap[left].Key) > 0)
						smallest = left;
					if (right < baseHeap.Count && comparer.Compare(baseHeap[smallest].Key, baseHeap[right].Key) > 0)
						smallest = right;

					if (smallest != pos)
					{
						ExchangeElements(smallest, pos);
						pos = smallest;
					}
					else break;
				}
			}

			public void Add(KeyValuePair<TPriority, TValue> item)
			{
				Enqueue(item.Key, item.Value);
			}

			public void Clear()
			{
				baseHeap.Clear();
			}

			public bool Contains(KeyValuePair<TPriority, TValue> item)
			{
				return baseHeap.Contains(item);
			}

			public int Count
			{
				get { return baseHeap.Count; }
			}

			public void CopyTo(KeyValuePair<TPriority, TValue>[] array, int arrayIndex)
			{
				baseHeap.CopyTo(array, arrayIndex);
			}

			public bool IsReadOnly
			{
				get { return false; }
			}

			public bool Remove(KeyValuePair<TPriority, TValue> item)
			{
				// find element in the collection and remove it
				int elementIdx = baseHeap.IndexOf(item);
				if (elementIdx < 0) return false;

				//remove element
				baseHeap[elementIdx] = baseHeap[baseHeap.Count - 1];
				baseHeap.RemoveAt(baseHeap.Count - 1);

				// heapify
				int newPos = HeapifyFromEndToBeginning(elementIdx);
				if (newPos == elementIdx)
					HeapifyFromBeginningToEnd(elementIdx);

				return true;
			}

			public IEnumerator<KeyValuePair<TPriority, TValue>> GetEnumerator()
			{
				return baseHeap.GetEnumerator();
			}

			IEnumerator IEnumerable.GetEnumerator()
			{
				return GetEnumerator();
			}
		}

		private static readonly Scanner cin = new Scanner();

		private static void Main()
		{
#if DEBUG
			var inputText = File.ReadAllText(@"..\..\input.txt");
			var testCases = inputText.Split(new[] { "input" }, StringSplitOptions.RemoveEmptyEntries);
			var consoleOut = Console.Out;
			for (var i = 0; i < testCases.Length; i++)
			{
				var parts = testCases[i].Split(new[] { "output" }, StringSplitOptions.RemoveEmptyEntries);
				Console.SetIn(new StringReader(parts[0].Trim()));
				var stringWriter = new StringWriter();
				Console.SetOut(stringWriter);
				var sw = Stopwatch.StartNew();
				new Template().Solve();
				sw.Stop();
				var output = stringWriter.ToString();

				Console.SetOut(consoleOut);
				var color = ConsoleColor.Green;
				var status = "Passed";
				if (parts[1].Trim() != output.Trim())
				{
					color = ConsoleColor.Red;
					status = "Failed";
				}
				Console.ForegroundColor = color;
				Console.WriteLine("Test {0} {1} in {2}ms", i + 1, status, sw.ElapsedMilliseconds);
			}
			Console.ReadLine();
			Console.ReadKey();
#else
			new Template().Solve();
			Console.ReadLine();
#endif
		}
	}

	internal class Scanner
	{
		private string[] s = new string[0];
		private int i;
		private readonly char[] cs = { ' ' };

		public string NextString()
		{
			if (i < s.Length) return s[i++];
			var line = Console.ReadLine() ?? string.Empty;
			s = line.Split(cs, StringSplitOptions.RemoveEmptyEntries);
			i = 1;
			return s.First();
		}

		public double NextDouble()
		{
			return double.Parse(NextString());
		}

		public int NextInt()
		{
			return int.Parse(NextString());
		}

		public long NextLong()
		{
			return long.Parse(NextString());
		}
	}
}


using System;
using System.Collections.Generic;
using System.IO;
using System.Text;

namespace Okabe_and_City
{
    internal class Program
    {
        private static readonly StreamReader reader = new StreamReader(Console.OpenStandardInput(1024*10), Encoding.ASCII, false, 1024*10);
        private static readonly StreamWriter writer = new StreamWriter(Console.OpenStandardOutput(1024*10), Encoding.ASCII, 1024*10);

        private static int[] p;

        private static int GP(int x)
        {
            if (p[x] == x)
                return x;
            return p[x] = GP(p[x]);
        }

        private static void Main(string[] args)
        {
            int n = Next();
            int m = Next();
            int k = Next();

            var x = new int[k];
            var y = new int[k];
            p = new int[k];
            for (int i = 0; i < k; i++)
            {
                x[i] = Next();
                y[i] = Next();
                p[i] = i;
            }

            var d = new Dictionary<int, int>();

            var dx = new[] {0, 0, 1, -1};
            var dy = new[] {1, -1, 0, 0};
            for (int i = 0; i < k; i++)
            {
                for (int j = 0; j < 4; j++)
                {
                    int mask = GM(x[i] + dx[j], y[i] + dy[j]);
                    if (d.ContainsKey(mask))
                    {
                        int pa = GP(d[mask]);
                        if (pa != i)
                            p[pa] = i;
                    }
                }
                d[GM(x[i], y[i])] = i;
            }

            var max = new int[k];
            var may = new int[k];
            var mix = new int[k];
            var miy = new int[k];

            for (int i = 0; i < k; i++)
            {
                mix[i] = int.MaxValue;
                miy[i] = int.MaxValue;
            }

            for (int i = 0; i < k; i++)
            {
                int pa = GP(i);
                max[pa] = Math.Max(max[pa], x[i]);
                mix[pa] = Math.Min(mix[pa], x[i]);
                may[pa] = Math.Max(may[pa], y[i]);
                miy[pa] = Math.Min(miy[pa], y[i]);
            }

            int pe = GM(n, m);
            if (d.ContainsKey(pe))
            {
                pe = GP(d[pe]);
            }
            else pe = -1;

            var list = new List<int>[k + (pe == -1 ? 1 : 0)];
            for (int i = 0; i < list.Length; i++)
            {
                list[i] = new List<int>();
            }

            for (int i = 0; i < k; i++)
            {
                if (p[i] != i)
                    continue;
                for (int j = 0; j < k; j++)
                {
                    if (p[j] != j || j == i)
                        continue;

                    if (Intersect(mix[i], max[i], mix[j], max[j]) || Intersect(miy[i], may[i], miy[j], may[j]))
                    {
                        list[i].Add(j);
                        list[j].Add(i);
                    }
                }
            }
            if (pe == -1)
            {
                pe = k;
                for (int i = 0; i < k; i++)
                {
                    if (p[i] != i)
                        continue;

                    if (max[i] >= n - 1 || may[i] >= m - 1)
                    {
                        list[i].Add(pe);
                        list[pe].Add(i);
                    }
                }
            }

            int p0 = GP(d[GM(1, 1)]);
            if (p0 == pe)
            {
                writer.WriteLine("0");
                writer.Flush();
                return;
            }
            var q = new Queue<int>();
            q.Enqueue(p0);
            var f = new bool[list.Length];
            f[p0] = true;
            var cost = new int[list.Length];
            cost[pe] = -1;
            while (q.Count > 0)
            {
                int t = q.Dequeue();

                foreach (int i in list[t])
                {
                    if (f[i]) continue;
                    f[i] = true;
                    cost[i] = 1 + cost[t];
                    q.Enqueue(i);
                }
            }

            writer.WriteLine(cost[pe]);
            writer.Flush();
        }

        private static bool Intersect(int mi1, int ma1, int mi2, int ma2)
        {
            if (mi1 > ma2 + 2)
                return false;
            if (mi2 > ma1 + 2)
                return false;

            return true;
        }

        private static int GM(int x, int y)
        {
            return (x << 16) + y;
        }

        private static int Next()
        {
            int c;
            int res = 0;
            do
            {
                c = reader.Read();
                if (c == -1)
                    return res;
            } while (c < '0' || c > '9');
            res = c - '0';
            while (true)
            {
                c = reader.Read();
                if (c < '0' || c > '9')
                    return res;
                res *= 10;
                res += c - '0';
            }
        }
    }
}


using System;
using System.Collections.Generic;
using System.IO;
using System.Text;

namespace Okabe_and_City
{
    internal class Program
    {
        private static readonly StreamReader reader = new StreamReader(Console.OpenStandardInput(1024*10), Encoding.ASCII, false, 1024*10);
        private static readonly StreamWriter writer = new StreamWriter(Console.OpenStandardOutput(1024*10), Encoding.ASCII, 1024*10);

        private static int[] p;

        private static int GP(int x)
        {
            if (p[x] == x)
                return x;
            return p[x] = GP(p[x]);
        }

        private static void Main(string[] args)
        {
            int n = Next();
            int m = Next();
            int k = Next();

            var x = new int[k];
            var y = new int[k];
            p = new int[k];
            for (int i = 0; i < k; i++)
            {
                x[i] = Next();
                y[i] = Next();
                p[i] = i;
            }

            var d = new Dictionary<int, int>();

            var dx = new[] {0, 0, 1, -1};
            var dy = new[] {1, -1, 0, 0};
            for (int i = 0; i < k; i++)
            {
                for (int j = 0; j < 4; j++)
                {
                    int mask = GM(x[i] + dx[j], y[i] + dy[j]);
                    if (d.ContainsKey(mask))
                    {
                        int pa = GP(d[mask]);
                        p[pa] = i;
                    }
                }
                d[GM(x[i], y[i])] = i;
            }

            var max = new int[k];
            var may = new int[k];
            var mix = new int[k];
            var miy = new int[k];

            for (int i = 0; i < k; i++)
            {
                mix[i] = int.MaxValue;
                miy[i] = int.MaxValue;
            }

            for (int i = 0; i < k; i++)
            {
                int pa = GP(i);
                max[pa] = Math.Max(max[pa], x[i]);
                mix[pa] = Math.Min(mix[pa], x[i]);
                may[pa] = Math.Max(may[pa], y[i]);
                miy[pa] = Math.Min(miy[pa], y[i]);
            }

            int pe = GM(n, m);
            if (d.ContainsKey(pe))
            {
                pe = GP(d[pe]);
            }
            else pe = -1;

            var list = new List<int>[k + (pe == -1 ? 1 : 0)];
            for (int i = 0; i < list.Length; i++)
            {
                list[i] = new List<int>();
            }

            for (int i = 0; i < k; i++)
            {
                if (p[i] != i)
                    continue;
                for (int j = 0; j < k; j++)
                {
                    if (p[j] != j || j == i)
                        continue;

                    if (Intersect(mix[i], max[i], mix[j], max[j]) || Intersect(miy[i], may[i], miy[j], may[j]))
                    {
                        list[i].Add(j);
                        list[j].Add(i);
                    }
                }
            }
            if (pe == -1)
            {
                pe = k;
                for (int i = 0; i < k; i++)
                {
                    if (p[i] != i)
                        continue;

                    if (Intersect(mix[i], max[i], n, n) || Intersect(miy[i], may[i], m, m))
                    {
                        list[i].Add(pe);
                        list[pe].Add(i);
                    }
                }
            }

            int p0 = GP(d[GM(1, 1)]);
            if (p0 == pe)
            {
                writer.WriteLine("0");
                writer.Flush();
                return;
            }
            var q = new Queue<int>();
            q.Enqueue(p0);
            var f = new bool[list.Length];
            f[p0] = true;
            var cost = new int[list.Length];
            cost[pe] = -1;
            while (q.Count > 0)
            {
                int t = q.Dequeue();

                foreach (int i in list[t])
                {
                    if (f[i]) continue;
                    f[i] = true;
                    cost[i] = 1 + cost[t];
                    q.Enqueue(i);
                }
            }

            writer.WriteLine(cost[pe]);
            writer.Flush();
        }

        private static bool Intersect(int mi1, int ma1, int mi2, int ma2)
        {
            if (mi1 > ma2 + 1)
                return false;
            if (mi2 > ma1 + 1)
                return false;

            return true;
        }

        private static int GM(int x, int y)
        {
            return (x << 16) + y;
        }

        private static int Next()
        {
            int c;
            int res = 0;
            do
            {
                c = reader.Read();
                if (c == -1)
                    return res;
            } while (c < '0' || c > '9');
            res = c - '0';
            while (true)
            {
                c = reader.Read();
                if (c < '0' || c > '9')
                    return res;
                res *= 10;
                res += c - '0';
            }
        }
    }
}


#include <stdio.h>
#include <stdlib.h>

#define N	10000
#define M	10000
#define K	10000

struct L {
	struct L *next;
	struct V *v;
	int w;
};

struct V {
	struct L adj;
	int i;
	int d;
} vv[K + N + M];

void list_add(struct L *head, struct V *v, int w) {
	struct L *l = malloc(sizeof *l);

	l->v = v;
	l->w = w;
	l->next = head->next; head->next = l;
}

int ii[K], jj[K];

int compare(const void *a, const void *b) {
	int h1 = *(int *) a;
	int h2 = *(int *) b;

	return ii[h1] != ii[h2] ? ii[h1] - ii[h2] : jj[h1] - jj[h2];
}

int main() {
	static int hh[K], qq[(K + N + M) * 2];
	int n, m, k, h, h1, h2, i, tmp, head, tail;

	scanf("%d%d%d", &n, &m, &k);
	for (h = 0; h < k; h++) {
		scanf("%d%d", &ii[h], &jj[h]);
		ii[h]--, jj[h]--;
		if (ii[h] > 0) {
			list_add(&vv[k + ii[h] - 1].adj, &vv[h], 0);
			list_add(&vv[h].adj, &vv[k + ii[h] - 1], 1);
		}
		list_add(&vv[k + ii[h]].adj, &vv[h], 0);
		list_add(&vv[h].adj, &vv[k + ii[h]], 1);
		if (ii[h] + 1 < n) {
			list_add(&vv[k + ii[h] + 1].adj, &vv[h], 0);
			list_add(&vv[h].adj, &vv[k + ii[h] + 1], 1);
		}
		if (jj[h] > 0) {
			list_add(&vv[k + n + jj[h] - 1].adj, &vv[h], 0);
			list_add(&vv[h].adj, &vv[k + n + jj[h] - 1], 1);
		}
		list_add(&vv[k + n + jj[h]].adj, &vv[h], 0);
		list_add(&vv[h].adj, &vv[k + n + jj[h]], 1);
		if (jj[h] + 1 < m) {
			list_add(&vv[k + n + jj[h] + 1].adj, &vv[h], 0);
			list_add(&vv[h].adj, &vv[k + n + jj[h] + 1], 1);
		}
	}
	for (h = 0; h < k; h++)
		hh[h] = h;
	qsort(hh, k, sizeof *hh, compare);
	for (h = 1; h < k; h++) {
		h1 = hh[h - 1];
		h2 = hh[h];
		if (ii[h1] == ii[h2] && jj[h1] + 1 == jj[h2]) {
			list_add(&vv[h1].adj, &vv[h2], 0);
			list_add(&vv[h2].adj, &vv[h1], 0);
		}
	}
	for (h = 0; h < k; h++)
		tmp = ii[h], ii[h] = jj[h], jj[h] = tmp;
	qsort(hh, k, sizeof *hh, compare);
	for (h = 1; h < k; h++) {
		h1 = hh[h - 1];
		h2 = hh[h];
		if (ii[h1] == ii[h2] && jj[h1] + 1 == jj[h2]) {
			list_add(&vv[h1].adj, &vv[h2], 0);
			list_add(&vv[h2].adj, &vv[h1], 0);
		}
	}
	for (h = 0; h < k; h++)
		tmp = ii[h], ii[h] = jj[h], jj[h] = tmp;
	for (i = 0; i < k + n + m; i++) {
		vv[i].i = i;
		vv[i].d = -1;
	}
	head = tail = K + N + M;
	vv[hh[0]].d = 0;
	qq[tail++] = hh[0];
	while (head < tail) {
		struct V *u = &vv[qq[head++]], *v;
		struct L *l;
		int d = u->d;

		if (u->i == k + n - 1 || u->i == k + n + m - 1 || (u->i < k && ii[u->i] == n - 1 && jj[u->i] == m - 1)) {
			printf("%d\n", u->d);
			return 0;
		}
		for (l = u->adj.next; l != NULL; l = l->next)
			if ((v = l->v)->d == -1) {
				v->d = d + l->w;
				if (l->w == 0)
					qq[--head] = v->i;
				else
					qq[tail++] = v->i;
			}
	}
	printf("-1\n");
	return 0;
}


#include <stdio.h>
#include <stdlib.h>

#define N	10000
#define M	10000
#define K	10000

struct L {
	struct L *next;
	struct V *v;
	int w;
};

struct V {
	struct L adj;
	int i;
	int d;
} vv[K + N + M];

void list_add(struct L *head, struct V *v, int w) {
	struct L *l = malloc(sizeof *l);

	l->v = v;
	l->w = w;
	l->next = head->next; head->next = l;
}

int ii[K], jj[K];

int compare(const void *a, const void *b) {
	int h1 = *(int *) a;
	int h2 = *(int *) b;

	return ii[h1] != ii[h2] ? ii[h1] - ii[h2] : jj[h1] - jj[h2];
}

int main() {
	static int hh[K], qq[(K + N + M) * 2];
	int n, m, k, h, h1, h2, i, tmp, head, tail;

	scanf("%d%d%d", &n, &m, &k);
	for (h = 0; h < k; h++) {
		scanf("%d%d", &ii[h], &jj[h]);
		ii[h]--, jj[h]--;
		if (ii[h] > 0) {
			list_add(&vv[k + ii[h] - 1].adj, &vv[h], 0);
			list_add(&vv[h].adj, &vv[k + ii[h] - 1], 1);
		}
		list_add(&vv[k + ii[h]].adj, &vv[h], 0);
		list_add(&vv[h].adj, &vv[k + ii[h]], 1);
		if (ii[h] + 1 < n) {
			list_add(&vv[k + ii[h] + 1].adj, &vv[h], 0);
			list_add(&vv[h].adj, &vv[k + ii[h] + 1], 1);
		}
		if (jj[h] > 0) {
			list_add(&vv[k + n + jj[h] - 1].adj, &vv[h], 0);
			list_add(&vv[h].adj, &vv[k + n + jj[h] + 1], 1);
		}
		list_add(&vv[k + n + jj[h]].adj, &vv[h], 0);
		list_add(&vv[h].adj, &vv[k + n + jj[h]], 1);
		if (jj[h] + 1 < m) {
			list_add(&vv[k + n + jj[h] + 1].adj, &vv[h], 0);
			list_add(&vv[h].adj, &vv[k + n + jj[h] + 1], 1);
		}
	}
	for (h = 0; h < k; h++)
		hh[h] = h;
	qsort(hh, k, sizeof *hh, compare);
	for (h = 1; h < k; h++) {
		h1 = hh[h - 1];
		h2 = hh[h];
		if (ii[h1] == ii[h2] && jj[h1] + 1 == jj[h2]) {
			list_add(&vv[h1].adj, &vv[h2], 0);
			list_add(&vv[h2].adj, &vv[h1], 0);
		}
	}
	for (h = 0; h < k; h++)
		tmp = ii[h], ii[h] = jj[h], jj[h] = tmp;
	qsort(hh, k, sizeof *hh, compare);
	for (h = 1; h < k; h++) {
		h1 = hh[h - 1];
		h2 = hh[h];
		if (ii[h1] == ii[h2] && jj[h1] + 1 == jj[h2]) {
			list_add(&vv[h1].adj, &vv[h2], 0);
			list_add(&vv[h2].adj, &vv[h1], 0);
		}
	}
	for (h = 0; h < k; h++)
		tmp = ii[h], ii[h] = jj[h], jj[h] = tmp;
	for (i = 0; i < k + n + m; i++) {
		vv[i].i = i;
		vv[i].d = -1;
	}
	head = tail = K + N + M;
	vv[hh[0]].d = 0;
	qq[tail++] = hh[0];
	while (head < tail) {
		struct V *u = &vv[qq[head++]], *v;
		struct L *l;
		int d = u->d;

		if (u->i == k + n - 1 || u->i == k + n + m - 1 || (u->i < k && ii[u->i] == n - 1 && jj[u->i] == m - 1)) {
			printf("%d\n", u->d);
			return 0;
		}
		for (l = u->adj.next; l != NULL; l = l->next)
			if ((v = l->v)->d == -1) {
				v->d = d + l->w;
				if (l->w == 0)
					qq[--head] = v->i;
				else
					qq[tail++] = v->i;
			}
	}
	printf("-1\n");
	return 0;
}


import java.awt.Point;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashSet;
import java.util.List;
import java.util.PriorityQueue;
import java.util.Scanner;
import java.util.Set;

// author : Benq

public class Ds{

	static boolean[] inRow;
	static boolean[] inCol;

	static boolean[] outRow;
	static boolean[] outCol;

	static int[][] dist;

	static int r;
	static int c;
	static int k;

	static List<Set<Integer>> litR = new ArrayList<>();
	static List<Set<Integer>> litC = new ArrayList<>();

	public static void main(String[] args) throws IOException {

		Scanner in = new Scanner(System.in);

		r = in.nextInt();
		c = in.nextInt();
		k = in.nextInt();

		inRow = new boolean[r];
		inCol = new boolean[c];

		outRow = new boolean[r];
		outCol = new boolean[c];

		dist = new int[r][c];

		for(int i=0; i<r; i++) {
			litR.add(new HashSet<>());
			litC.add(new HashSet<>());

		}

		for(int i=0; i<k; i++) {

			int rr = in.nextInt()-1;
			int cc = in.nextInt()-1;

			litR.get(rr).add(cc);
			litC.get(cc).add(rr);

		}

		PriorityQueue<Triple> pq = new PriorityQueue<>(new Comparator<Triple>() {
			@Override
			public int compare(Triple o1, Triple o2) {
				return o1.dist - o2.dist;
			}
		});

		for(int i=0; i<r; i++) {
			for(int j=0; j<c; j++) {
				dist[i][j] = Integer.MAX_VALUE;
			}
		}

		pq.offer(new Triple(0, 0, 0));
		dist[0][0] = 0;

		while(!pq.isEmpty()) {

			Triple cur = pq.poll();

			if(cur.dist > dist[cur.x][cur.y]) {
				continue;
			}

			if(litR.get(cur.x).contains(cur.y)) {

				// relax one aways
				relaxRow(cur.x-1, pq, false, cur);
				relaxRow(cur.x+1, pq, false, cur);

				relaxCol(cur.y-1, pq, false, cur);
				relaxCol(cur.y+1, pq, false, cur);

				//relax on
				relaxRow(cur.x, pq, true, cur);
				relaxCol(cur.y, pq, true, cur);

			}

			if(litR.get(cur.x).contains(cur.y-1)) {
				if(cur.dist  < dist[cur.x][cur.y-1]) {
					dist[cur.x][cur.y-1] = cur.dist;
					pq.offer(new Triple(cur.x, cur.y-1, cur.dist));
				}
			}

			if(litR.get(cur.x).contains(cur.y+1)) {
				if(cur.dist  < dist[cur.x][cur.y+1]) {
					dist[cur.x][cur.y+1] = cur.dist;
					pq.offer(new Triple(cur.x, cur.y+1, cur.dist));
				}
			}

			if(litC.get(cur.y).contains(cur.x+1)) {
				if(cur.dist  < dist[cur.x+1][cur.y]) {
					dist[cur.x+1][cur.y] = cur.dist;
					pq.offer(new Triple(cur.x+1, cur.y, cur.dist));
				}
			}

			if(litC.get(cur.y).contains(cur.x-1)) {
				if(cur.dist  < dist[cur.x-1][cur.y]) {
					dist[cur.x-1][cur.y] = cur.dist;
					pq.offer(new Triple(cur.x-1, cur.y, cur.dist));
				}
			}

		}

		System.out.println(dist[r-1][c-1] == Integer.MAX_VALUE ? -1 : dist[r-1][c-1]);

	}

	private static void relaxCol(int curCol, PriorityQueue<Triple> pq, boolean in, Triple cur) {

		boolean[] mark = in ? inCol : outCol;

		if(curCol < 0 || curCol >= r || mark[curCol]) {
			return;
		}

		for(int i=0; i<r; i++) {

			if(cur.dist + 1 < dist[i][curCol]) {
				dist[i][curCol] = cur.dist + 1;
				pq.offer(new Triple(i, curCol, cur.dist + 1));
			}

		}

		mark[curCol] = true;

	}

	private static void relaxRow(int curRow, PriorityQueue<Triple> pq, boolean in, Triple cur) {

		boolean[] mark = in ? inRow : outRow;

		if(curRow < 0 || curRow >= r || mark[curRow]) {
			return;
		}

		for(int i=0; i<c; i++) {

			if(cur.dist + 1 < dist[curRow][i]) {
				dist[curRow][i] = cur.dist + 1;
				pq.offer(new Triple(curRow, i, cur.dist + 1));
			}

		}

		mark[curRow] = true;

	}

}

class Triple {
	public Triple(int x, int y, int dist) {
		super();
		this.x = x;
		this.y = y;
		this.dist = dist;
	}

	int x, y, dist;

}


import java.awt.Point;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.PriorityQueue;
import java.util.Scanner;
import java.util.Set;

// author : Benq

public class Ds{

	static int r;
	static int c;
	static int k;

	static List<Set<Integer>> litR = new ArrayList<>();
	static List<Set<Integer>> litC = new ArrayList<>();

	static boolean[] usedRow;
	static boolean[] usedCol;

	static int[] dist;

	static Map<PII, Integer> map = new HashMap<>();

	public static void main(String[] args) throws IOException {

		Scanner in = new Scanner(System.in);

		r = in.nextInt();
		c = in.nextInt();
		k = in.nextInt();

		usedRow = new boolean[r];
		usedCol = new boolean[c];

		dist = new int[k];

		for(int i=0; i<r; i++) {
			litR.add(new HashSet<>());
		}

		for(int i=0; i<c; i++) {
			litC.add(new HashSet<>());
		}

		for(int i=0; i<k; i++) {

			int rr = in.nextInt()-1;
			int cc = in.nextInt()-1;

			litR.get(rr).add(cc);
			litC.get(cc).add(rr);

			map.put(new PII(rr,cc), i);

			dist[i] = Integer.MAX_VALUE;

		}

		PriorityQueue<Triple> pq = new PriorityQueue<>(new Comparator<Triple>() {
			@Override
			public int compare(Triple o1, Triple o2) {
				return o1.dist - o2.dist;
			}
		});

		pq.add(new Triple(0, 0, 0));

		int[] dx = {-1, 0, 1, 0};
		int[] dy = {0, 1, 0, -1};

		dist[map.get(new PII(0,0))] = 0;

		while(!pq.isEmpty()) {

			Triple cur = pq.poll();

			if(cur.dist > dist[map.get(new PII(cur.x, cur.y))]) {
				continue;
			}

			for(int i=cur.x-2; i<=cur.x+2; i++) {
				relaxRow(i, pq, cur);
			}
			for(int i=cur.y-2; i<=cur.y+2; i++) {
				relaxCol(i, pq, cur);
			}

			for(int i=0; i<4; i++) {

				int nr = cur.x + dx[i];
				int nc = cur.y + dy[i];

				if(nr >= 0 && nc >= 0 && nr < r && nc < c && litR.get(nr).contains(nc) && cur.dist < dist[map.get(new PII(nr,nc))]) {
					dist[map.get(new PII(nr,nc))] = cur.dist;
					pq.offer(new Triple(nr, nc, cur.dist));
				}

			}

		}

		int ans = Integer.MAX_VALUE;

		if(litR.get(r-1).contains(c-1)) {
			ans = dist[map.get(new PII(r-1, c-1))];
			System.out.println(ans == Integer.MAX_VALUE ? -1 : ans);
			return;

		}

		for(int x : litR.get(r-1)) {
			ans = Math.min(ans, dist[map.get(new PII(r-1, x))]) ;
		}

		for(int x : litR.get(r-2)) {
			ans = Math.min(ans, dist[map.get(new PII(r-2, x))]) ;
		}

		for(int x : litC.get(c-1)) {
			ans = Math.min(ans, dist[map.get(new PII(x, c-1))]) ;
		}

		for(int x : litC.get(c-2)) {
			ans = Math.min(ans, dist[map.get(new PII(x, c-2))]) ;
		}

		System.out.println(ans == Integer.MAX_VALUE ? -1 : ans + 1);

	}

	private static void relaxCol(int curCol, PriorityQueue<Triple> pq, Triple cur) {

		if(curCol < 0 || curCol >= c || usedCol[curCol]) {
			return;
		}

		for(int rr : litC.get(curCol)) {

			if(cur.dist + 1 < dist[map.get(new PII(rr, curCol))]) {
				dist[map.get(new PII(rr, curCol))] = cur.dist + 1;
				pq.offer(new Triple(rr, curCol, cur.dist+1));
			}
		}

		usedCol[curCol] = true;

	}

	private static void relaxRow(int curRow, PriorityQueue<Triple> pq, Triple cur) {

		if(curRow < 0 || curRow >= r || usedRow[curRow]) {
			return;
		}

		for(int cc : litR.get(curRow)) {

			if(cur.dist + 1 < dist[map.get(new PII(curRow, cc))]) {
				dist[map.get(new PII(curRow, cc))] = cur.dist + 1;
				pq.offer(new Triple(curRow, cc, cur.dist+1));
			}
		}

		usedRow[curRow] = true;

	}

}

class PII extends Point {

	public PII(int rr, int cc) {
		super(rr, cc);
	}

	@Override
	public int hashCode() {
		return  (31*x) + (31*y);
	}
}
class Triple {
	public Triple(int x, int y, int dist) {
		super();
		this.x = x;
		this.y = y;
		this.dist = dist;
	}

	int x, y, dist;

}


package checker;

import java.awt.Point;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.PriorityQueue;
import java.util.Scanner;
import java.util.Set;

// author : Benq

public class Ds{

	static int r;
	static int c;
	static int k;

	static List<Set<Integer>> litR = new ArrayList<>();
	static List<Set<Integer>> litC = new ArrayList<>();

	static boolean[] usedRow;
	static boolean[] usedCol;

	static int[] dist;

	static Map<PII, Integer> map = new HashMap<>();

	public static void main(String[] args) throws IOException {

		Scanner in = new Scanner(System.in);

		r = in.nextInt();
		c = in.nextInt();
		k = in.nextInt();

		usedRow = new boolean[r];
		usedCol = new boolean[c];

		dist = new int[k];

		for(int i=0; i<r; i++) {
			litR.add(new HashSet<>());
		}

		for(int i=0; i<c; i++) {
			litC.add(new HashSet<>());
		}

		for(int i=0; i<k; i++) {

			int rr = in.nextInt()-1;
			int cc = in.nextInt()-1;

			litR.get(rr).add(cc);
			litC.get(cc).add(rr);

			map.put(new PII(rr,cc), i);

			dist[i] = Integer.MAX_VALUE;

		}

		PriorityQueue<Triple> pq = new PriorityQueue<>(new Comparator<Triple>() {
			@Override
			public int compare(Triple o1, Triple o2) {
				return o1.x - o2.x;
			}
		});

		pq.add(new Triple(0, 0, 0));

		int[] dx = {-1, 0, 1, 0};
		int[] dy = {0, 1, 0, -1};

		dist[map.get(new PII(0,0))] = 0;

		while(!pq.isEmpty()) {

			Triple cur = pq.poll();

			if(cur.dist > dist[map.get(new PII(cur.x, cur.y))]) {
				continue;
			}

			for(int i=cur.x-2; i<=cur.x+2; i++) {
				relaxRow(i, pq, cur);
			}
			for(int i=cur.y-2; i<=cur.y+2; i++) {
				relaxCol(i, pq, cur);
			}

			for(int i=0; i<4; i++) {

				int nr = cur.x + dx[i];
				int nc = cur.y + dy[i];

				if(nr >= 0 && nc >= 0 && nr < r && nc < c && litR.get(nr).contains(nc) && cur.dist < dist[map.get(new PII(nr,nc))]) {
					dist[map.get(new PII(nr,nc))] = cur.dist;
					pq.offer(new Triple(nr, nc, cur.dist));
				}

			}

		}

		int ans = Integer.MAX_VALUE;

		if(litR.get(r-1).contains(c-1)) {
			ans = dist[map.get(new PII(r-1, c-1))];
			System.out.println(ans == Integer.MAX_VALUE ? -1 : ans);
			return;

		}

		for(int x : litR.get(r-1)) {
			ans = Math.min(ans, dist[map.get(new PII(r-1, x))]) ;
		}

		for(int x : litR.get(r-2)) {
			ans = Math.min(ans, dist[map.get(new PII(r-2, x))]) ;
		}

		for(int x : litC.get(c-1)) {
			ans = Math.min(ans, dist[map.get(new PII(x, c-1))]) ;
		}

		for(int x : litC.get(c-2)) {
			ans = Math.min(ans, dist[map.get(new PII(x, c-2))]) ;
		}

		System.out.println(ans == Integer.MAX_VALUE ? -1 : ans + 1);

	}

	private static void relaxCol(int curCol, PriorityQueue<Triple> pq, Triple cur) {

		if(curCol < 0 || curCol >= c || usedCol[curCol]) {
			return;
		}

		for(int rr : litC.get(curCol)) {

			if(cur.dist + 1 < dist[map.get(new PII(rr, curCol))]) {
				dist[map.get(new PII(rr, curCol))] = cur.dist + 1;
				pq.offer(new Triple(rr, curCol, cur.dist+1));
			}
		}

		usedCol[curCol] = true;

	}

	private static void relaxRow(int curRow, PriorityQueue<Triple> pq, Triple cur) {

		if(curRow < 0 || curRow >= r || usedRow[curRow]) {
			return;
		}

		for(int cc : litR.get(curRow)) {

			if(cur.dist + 1 < dist[map.get(new PII(curRow, cc))]) {
				dist[map.get(new PII(curRow, cc))] = cur.dist + 1;
				pq.offer(new Triple(curRow, cc, cur.dist+1));
			}
		}

		usedRow[curRow] = true;

	}

}

class PII extends Point {

	public PII(int rr, int cc) {
		super(rr, cc);
	}

	@Override
	public int hashCode() {
		return  (31*x) + (31*y);
	}
}
class Triple {
	public Triple(int x, int y, int dist) {
		super();
		this.x = x;
		this.y = y;
		this.dist = dist;
	}

	int x, y, dist;

}


package checker;

import java.awt.Point;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.PriorityQueue;
import java.util.Scanner;
import java.util.Set;

// author : Benq

public class Ds{

	static int r;
	static int c;
	static int k;

	static List<Set<Integer>> litR = new ArrayList<>();
	static List<Set<Integer>> litC = new ArrayList<>();

	static boolean[] usedRow;
	static boolean[] usedCol;

	static int[] dist;

	static Map<PII, Integer> map = new HashMap<>();

	public static void main(String[] args) throws IOException {

		Scanner in = new Scanner(System.in);

		r = in.nextInt();
		c = in.nextInt();
		k = in.nextInt();

		usedRow = new boolean[r];
		usedCol = new boolean[c];

		dist = new int[k];

		for(int i=0; i<r; i++) {
			litR.add(new HashSet<>());
		}

		for(int i=0; i<c; i++) {
			litC.add(new HashSet<>());
		}

		for(int i=0; i<k; i++) {

			int rr = in.nextInt()-1;
			int cc = in.nextInt()-1;

			litR.get(rr).add(cc);
			litC.get(cc).add(rr);

			map.put(new PII(rr,cc), i);

			dist[i] = Integer.MAX_VALUE;

		}

		PriorityQueue<Triple> pq = new PriorityQueue<>(new Comparator<Triple>() {
			@Override
			public int compare(Triple o1, Triple o2) {
				return o1.dist - o2.dist;
			}
		});

		pq.add(new Triple(0, 0, 0));

		int[] dx = {-1, 0, 1, 0};
		int[] dy = {0, 1, 0, -1};

		dist[map.get(new PII(0,0))] = 0;

		while(!pq.isEmpty()) {

			Triple cur = pq.poll();

			if(cur.dist > dist[map.get(new PII(cur.x, cur.y))]) {
				continue;
			}

			for(int i=cur.x-2; i<=cur.x+2; i++) {
				relaxRow(i, pq, cur);
			}
			for(int i=cur.y-2; i<=cur.y+2; i++) {
				relaxCol(i, pq, cur);
			}

			for(int i=0; i<4; i++) {

				int nr = cur.x + dx[i];
				int nc = cur.y + dy[i];

				if(nr >= 0 && nc >= 0 && nr < r && nc < c && litR.get(nr).contains(nc) && cur.dist < dist[map.get(new PII(nr,nc))]) {
					dist[map.get(new PII(nr,nc))] = cur.dist;
					pq.offer(new Triple(nr, nc, cur.dist));
				}

			}

		}

		int ans = Integer.MAX_VALUE;

		if(litR.get(r-1).contains(c-1)) {
			ans = dist[map.get(new PII(r-1, c-1))];
			System.out.println(ans == Integer.MAX_VALUE ? -1 : ans);
			return;

		}

		for(int x : litR.get(r-1)) {
			ans = Math.min(ans, dist[map.get(new PII(r-1, x))]) ;
		}

		for(int x : litR.get(r-2)) {
			ans = Math.min(ans, dist[map.get(new PII(r-2, x))]) ;
		}

		for(int x : litC.get(c-1)) {
			ans = Math.min(ans, dist[map.get(new PII(x, c-1))]) ;
		}

		for(int x : litC.get(c-2)) {
			ans = Math.min(ans, dist[map.get(new PII(x, c-2))]) ;
		}

		System.out.println(ans == Integer.MAX_VALUE ? -1 : ans + 1);

	}

	private static void relaxCol(int curCol, PriorityQueue<Triple> pq, Triple cur) {

		if(curCol < 0 || curCol >= c || usedCol[curCol]) {
			return;
		}

		for(int rr : litC.get(curCol)) {

			if(cur.dist + 1 < dist[map.get(new PII(rr, curCol))]) {
				dist[map.get(new PII(rr, curCol))] = cur.dist + 1;
				pq.offer(new Triple(rr, curCol, cur.dist+1));
			}
		}

		usedCol[curCol] = true;

	}

	private static void relaxRow(int curRow, PriorityQueue<Triple> pq, Triple cur) {

		if(curRow < 0 || curRow >= r || usedRow[curRow]) {
			return;
		}

		for(int cc : litR.get(curRow)) {

			if(cur.dist + 1 < dist[map.get(new PII(curRow, cc))]) {
				dist[map.get(new PII(curRow, cc))] = cur.dist + 1;
				pq.offer(new Triple(curRow, cc, cur.dist+1));
			}
		}

		usedRow[curRow] = true;

	}

}

class PII extends Point {

	public PII(int rr, int cc) {
		super(rr, cc);
	}

	@Override
	public int hashCode() {
		return  (31*x) + (31*y);
	}
}
class Triple {
	public Triple(int x, int y, int dist) {
		super();
		this.x = x;
		this.y = y;
		this.dist = dist;
	}

	int x, y, dist;

}


import java.awt.Point;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.PriorityQueue;
import java.util.Scanner;
import java.util.Set;

// author : Benq

public class Ds{

	static int r;
	static int c;
	static int k;

	static List<Set<Integer>> litR = new ArrayList<>();
	static List<Set<Integer>> litC = new ArrayList<>();

	static boolean[] usedRow;
	static boolean[] usedCol;

	static int[] dist;

	static Map<PII, Integer> map = new HashMap<>();

	public static void main(String[] args) throws IOException {

		Scanner in = new Scanner(System.in);

		r = in.nextInt();
		c = in.nextInt();
		k = in.nextInt();

		usedRow = new boolean[r];
		usedCol = new boolean[c];

		dist = new int[k];

		for(int i=0; i<r; i++) {
			litR.add(new HashSet<>());
		}

		for(int i=0; i<c; i++) {
			litC.add(new HashSet<>());
		}

		for(int i=0; i<k; i++) {

			int rr = in.nextInt()-1;
			int cc = in.nextInt()-1;

			litR.get(rr).add(cc);
			litC.get(cc).add(rr);

			map.put(new PII(rr,cc), i);

			dist[i] = Integer.MAX_VALUE;

		}

		PriorityQueue<Triple> pq = new PriorityQueue<>(new Comparator<Triple>() {
			@Override
			public int compare(Triple o1, Triple o2) {
				return o1.x - o2.x;
			}
		});

		pq.add(new Triple(0, 0, 0));

		int[] dx = {-1, 0, 1, 0};
		int[] dy = {0, 1, 0, -1};

		dist[map.get(new PII(0,0))] = 0;

		while(!pq.isEmpty()) {

			Triple cur = pq.poll();

			if(cur.dist > dist[map.get(new PII(cur.x, cur.y))]) {
				continue;
			}

			for(int i=cur.x-2; i<=cur.x+2; i++) {
				relaxRow(i, pq, cur);
			}
			for(int i=cur.y-2; i<=cur.y+2; i++) {
				relaxCol(i, pq, cur);
			}

			for(int i=0; i<4; i++) {

				int nr = cur.x + dx[i];
				int nc = cur.y + dy[i];

				if(nr >= 0 && nc >= 0 && nr < r && nc < c && litR.get(nr).contains(nc) && cur.dist < dist[map.get(new PII(nr,nc))]) {
					dist[map.get(new PII(nr,nc))] = cur.dist;
					pq.offer(new Triple(nr, nc, cur.dist));
				}

			}

		}

		int ans = Integer.MAX_VALUE;

		if(litR.get(r-1).contains(c-1)) {
			ans = dist[map.get(new PII(r-1, c-1))];
			System.out.println(ans == Integer.MAX_VALUE ? -1 : ans);
			return;

		}

		for(int x : litR.get(r-1)) {
			ans = Math.min(ans, dist[map.get(new PII(r-1, x))]) ;
		}

		for(int x : litR.get(r-2)) {
			ans = Math.min(ans, dist[map.get(new PII(r-2, x))]) ;
		}

		for(int x : litC.get(c-1)) {
			ans = Math.min(ans, dist[map.get(new PII(x, c-1))]) ;
		}

		for(int x : litC.get(c-2)) {
			ans = Math.min(ans, dist[map.get(new PII(x, c-2))]) ;
		}

		System.out.println(ans == Integer.MAX_VALUE ? -1 : ans + 1);

	}

	private static void relaxCol(int curCol, PriorityQueue<Triple> pq, Triple cur) {

		if(curCol < 0 || curCol >= c || usedCol[curCol]) {
			return;
		}

		for(int rr : litC.get(curCol)) {

			if(cur.dist + 1 < dist[map.get(new PII(rr, curCol))]) {
				dist[map.get(new PII(rr, curCol))] = cur.dist + 1;
				pq.offer(new Triple(rr, curCol, cur.dist+1));
			}
		}

		usedCol[curCol] = true;

	}

	private static void relaxRow(int curRow, PriorityQueue<Triple> pq, Triple cur) {

		if(curRow < 0 || curRow >= r || usedRow[curRow]) {
			return;
		}

		for(int cc : litR.get(curRow)) {

			if(cur.dist + 1 < dist[map.get(new PII(curRow, cc))]) {
				dist[map.get(new PII(curRow, cc))] = cur.dist + 1;
				pq.offer(new Triple(curRow, cc, cur.dist+1));
			}
		}

		usedCol[curRow] = true;

	}

}

class PII extends Point {

	public PII(int rr, int cc) {
		super(rr, cc);
	}

	@Override
	public int hashCode() {
		return  (31*x) + (31*y);
	}
}

class Triple {
	public Triple(int x, int y, int dist) {
		super();
		this.x = x;
		this.y = y;
		this.dist = dist;
	}

	int x, y, dist;

}


import java.awt.Point;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashSet;
import java.util.List;
import java.util.PriorityQueue;
import java.util.Scanner;
import java.util.Set;

// author : Benq

public class Ds{

	static boolean[] inRow;
	static boolean[] inCol;

	static boolean[] outRow;
	static boolean[] outCol;

	static int[][] dist;

	static int r;
	static int c;
	static int k;

	static List<Set<Integer>> litR = new ArrayList<>();
	static List<Set<Integer>> litC = new ArrayList<>();

	public static void main(String[] args) throws IOException {

		Scanner in = new Scanner(System.in);

		r = in.nextInt();
		c = in.nextInt();
		k = in.nextInt();

		inRow = new boolean[r];
		inCol = new boolean[c];

		outRow = new boolean[r];
		outCol = new boolean[c];

		dist = new int[r][c];

		for(int i=0; i<r; i++) {
			litR.add(new HashSet<>());
		}

		for(int i=0; i<c; i++) {
			litC.add(new HashSet<>());
		}

		for(int i=0; i<k; i++) {

			int rr = in.nextInt()-1;
			int cc = in.nextInt()-1;

			litR.get(rr).add(cc);
			litC.get(cc).add(rr);

		}

		PriorityQueue<Triple> pq = new PriorityQueue<>(new Comparator<Triple>() {
			@Override
			public int compare(Triple o1, Triple o2) {
				return o1.dist - o2.dist;
			}
		});

		for(int i=0; i<r; i++) {
			for(int j=0; j<c; j++) {
				dist[i][j] = Integer.MAX_VALUE;
			}
		}

		pq.offer(new Triple(0, 0, 0));
		dist[0][0] = 0;

		while(!pq.isEmpty()) {

			Triple cur = pq.poll();

			if(cur.dist > dist[cur.x][cur.y]) {
				continue;
			}

			if(litR.get(cur.x).contains(cur.y)) {

				// relax one aways
				relaxRow(cur.x-1, pq, false, cur);
				relaxRow(cur.x+1, pq, false, cur);

				relaxCol(cur.y-1, pq, false, cur);
				relaxCol(cur.y+1, pq, false, cur);

				//relax on
				relaxRow(cur.x, pq, true, cur);
				relaxCol(cur.y, pq, true, cur);

			}

			if(litR.get(cur.x).contains(cur.y-1)) {
				if(cur.dist  < dist[cur.x][cur.y-1]) {
					dist[cur.x][cur.y-1] = cur.dist;
					pq.offer(new Triple(cur.x, cur.y-1, cur.dist));
				}
			}

			if(litR.get(cur.x).contains(cur.y+1)) {
				if(cur.dist  < dist[cur.x][cur.y+1]) {
					dist[cur.x][cur.y+1] = cur.dist;
					pq.offer(new Triple(cur.x, cur.y+1, cur.dist));
				}
			}

			if(litC.get(cur.y).contains(cur.x+1)) {
				if(cur.dist  < dist[cur.x+1][cur.y]) {
					dist[cur.x+1][cur.y] = cur.dist;
					pq.offer(new Triple(cur.x+1, cur.y, cur.dist));
				}
			}

			if(litC.get(cur.y).contains(cur.x-1)) {
				if(cur.dist  < dist[cur.x-1][cur.y]) {
					dist[cur.x-1][cur.y] = cur.dist;
					pq.offer(new Triple(cur.x-1, cur.y, cur.dist));
				}
			}

		}

		System.out.println(dist[r-1][c-1] == Integer.MAX_VALUE ? -1 : dist[r-1][c-1]);

	}

	private static void relaxCol(int curCol, PriorityQueue<Triple> pq, boolean in, Triple cur) {

		boolean[] mark = in ? inCol : outCol;

		if(curCol < 0 || curCol >= c || mark[curCol]) {
			return;
		}

		for(int i=0; i<r; i++) {

			if(cur.dist + 1 < dist[i][curCol]) {
				dist[i][curCol] = cur.dist + 1;
				pq.offer(new Triple(i, curCol, cur.dist + 1));
			}

		}

		mark[curCol] = true;

	}

	private static void relaxRow(int curRow, PriorityQueue<Triple> pq, boolean in, Triple cur) {

		boolean[] mark = in ? inRow : outRow;

		if(curRow < 0 || curRow >= r || mark[curRow]) {
			return;
		}

		for(int i=0; i<c; i++) {

			if(cur.dist + 1 < dist[curRow][i]) {
				dist[curRow][i] = cur.dist + 1;
				pq.offer(new Triple(curRow, i, cur.dist + 1));
			}

		}

		mark[curRow] = true;

	}

}

class Triple {
	public Triple(int x, int y, int dist) {
		super();
		this.x = x;
		this.y = y;
		this.dist = dist;
	}

	int x, y, dist;

}


import java.awt.Point;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashSet;
import java.util.List;
import java.util.PriorityQueue;
import java.util.Scanner;
import java.util.Set;

// author : Benq

public class Ds{

	static boolean[] inRow;
	static boolean[] inCol;

	static boolean[] outRow;
	static boolean[] outCol;

	static int[][] dist;

	static int r;
	static int c;
	static int k;

	static List<Set<Integer>> litR = new ArrayList<>();
	static List<Set<Integer>> litC = new ArrayList<>();

	public static void main(String[] args) throws IOException {

		Scanner in = new Scanner(System.in);

		r = in.nextInt();
		c = in.nextInt();
		k = in.nextInt();

		inRow = new boolean[r];
		inCol = new boolean[c];

		outRow = new boolean[r];
		outCol = new boolean[c];

		dist = new int[r][c];

		for(int i=0; i<r; i++) {
			litR.add(new HashSet<>());
		}

		for(int i=0; i<c; i++) {
			litC.add(new HashSet<>());
		}

		for(int i=0; i<k; i++) {

			int rr = in.nextInt()-1;
			int cc = in.nextInt()-1;

			litR.get(rr).add(cc);
			litC.get(cc).add(rr);

		}

		PriorityQueue<Triple> pq = new PriorityQueue<>(new Comparator<Triple>() {
			@Override
			public int compare(Triple o1, Triple o2) {
				return o1.dist - o2.dist;
			}
		});

		for(int i=0; i<r; i++) {
			for(int j=0; j<c; j++) {
				dist[i][j] = Integer.MAX_VALUE;
			}
		}

		pq.offer(new Triple(0, 0, 0));
		dist[0][0] = 0;

		while(!pq.isEmpty()) {

			Triple cur = pq.poll();

			if(cur.dist > dist[cur.x][cur.y]) {
				continue;
			}

			if(litR.get(cur.x).contains(cur.y)) {

				// relax one aways
				relaxRow(cur.x-1, pq, false, cur);
				relaxRow(cur.x+1, pq, false, cur);

				relaxCol(cur.y-1, pq, false, cur);
				relaxCol(cur.y+1, pq, false, cur);

				//relax on
				relaxRow(cur.x, pq, true, cur);
				relaxCol(cur.y, pq, true, cur);

			}

			if(litR.get(cur.x).contains(cur.y-1)) {
				if(cur.dist  < dist[cur.x][cur.y-1]) {
					dist[cur.x][cur.y-1] = cur.dist;
					pq.offer(new Triple(cur.x, cur.y-1, cur.dist));
				}
			}

			if(litR.get(cur.x).contains(cur.y+1)) {
				if(cur.dist  < dist[cur.x][cur.y+1]) {
					dist[cur.x][cur.y+1] = cur.dist;
					pq.offer(new Triple(cur.x, cur.y+1, cur.dist));
				}
			}

			if(litC.get(cur.y).contains(cur.x+1)) {
				if(cur.dist  < dist[cur.x+1][cur.y]) {
					dist[cur.x+1][cur.y] = cur.dist;
					pq.offer(new Triple(cur.x+1, cur.y, cur.dist));
				}
			}

			if(litC.get(cur.y).contains(cur.x-1)) {
				if(cur.dist  < dist[cur.x-1][cur.y]) {
					dist[cur.x-1][cur.y] = cur.dist;
					pq.offer(new Triple(cur.x-1, cur.y, cur.dist));
				}
			}

		}

		System.out.println(dist[r-1][c-1] == Integer.MAX_VALUE ? -1 : dist[r-1][c-1]);

	}

	private static void relaxCol(int curCol, PriorityQueue<Triple> pq, boolean in, Triple cur) {

		boolean[] mark = in ? inCol : outCol;

		if(curCol < 0 || curCol >= r || mark[curCol]) {
			return;
		}

		for(int i=0; i<r; i++) {

			if(cur.dist + 1 < dist[i][curCol]) {
				dist[i][curCol] = cur.dist + 1;
				pq.offer(new Triple(i, curCol, cur.dist + 1));
			}

		}

		mark[curCol] = true;

	}

	private static void relaxRow(int curRow, PriorityQueue<Triple> pq, boolean in, Triple cur) {

		boolean[] mark = in ? inRow : outRow;

		if(curRow < 0 || curRow >= r || mark[curRow]) {
			return;
		}

		for(int i=0; i<c; i++) {

			if(cur.dist + 1 < dist[curRow][i]) {
				dist[curRow][i] = cur.dist + 1;
				pq.offer(new Triple(curRow, i, cur.dist + 1));
			}

		}

		mark[curRow] = true;

	}

}

class Triple {
	public Triple(int x, int y, int dist) {
		super();
		this.x = x;
		this.y = y;
		this.dist = dist;
	}

	int x, y, dist;

}


import java.awt.Point;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.PriorityQueue;
import java.util.Scanner;
import java.util.Set;

// author : Benq

public class Ds{

	static int r;
	static int c;
	static int k;

	static List<Set<Integer>> litR = new ArrayList<>();
	static List<Set<Integer>> litC = new ArrayList<>();

	static boolean[] usedRow;
	static boolean[] usedCol;

	static int[] dist;

	static Map<PII, Integer> map = new HashMap<>();

	public static void main(String[] args) throws IOException {

		Scanner in = new Scanner(System.in);

		r = in.nextInt();
		c = in.nextInt();
		k = in.nextInt();

		usedRow = new boolean[r];
		usedCol = new boolean[c];

		dist = new int[k];

		for(int i=0; i<r; i++) {
			litR.add(new HashSet<>());
		}

		for(int i=0; i<c; i++) {
			litC.add(new HashSet<>());
		}

		for(int i=0; i<k; i++) {

			int rr = in.nextInt()-1;
			int cc = in.nextInt()-1;

			litR.get(rr).add(cc);
			litC.get(cc).add(rr);

			map.put(new PII(rr,cc), i);

			dist[i] = Integer.MAX_VALUE;

		}

		PriorityQueue<Triple> pq = new PriorityQueue<>(new Comparator<Triple>() {
			@Override
			public int compare(Triple o1, Triple o2) {
				return o1.x - o2.x;
			}
		});

		pq.add(new Triple(0, 0, 0));

		int[] dx = {-1, 0, 1, 0};
		int[] dy = {0, 1, 0, -1};

		dist[map.get(new PII(0,0))] = 0;

		while(!pq.isEmpty()) {

			Triple cur = pq.poll();

			if(cur.dist > dist[map.get(new PII(cur.x, cur.y))]) {
				continue;
			}

			for(int i=cur.x-2; i<=cur.x+2; i++) {
				relaxRow(i, pq, cur);
			}
			for(int i=cur.y-2; i<=cur.y+2; i++) {
				relaxCol(i, pq, cur);
			}

			for(int i=0; i<4; i++) {

				int nr = cur.x + dx[i];
				int nc = cur.y + dy[i];

				if(nr >= 0 && nc >= 0 && nr < r && nc < c && litR.get(nr).contains(nc) && cur.dist < dist[map.get(new PII(nr,nc))]) {
					dist[map.get(new PII(nr,nc))] = cur.dist;
					pq.offer(new Triple(nr, nc, cur.dist));
				}

			}

		}

		int ans = Integer.MAX_VALUE;

		if(litR.get(r-1).contains(c-1)) {
			ans = dist[map.get(new PII(r-1, c-1))];
			System.out.println(ans == Integer.MAX_VALUE ? -1 : ans);
			return;

		}

		for(int x : litR.get(r-1)) {
			ans = Math.min(ans, dist[map.get(new PII(r-1, x))]) ;
		}

		for(int x : litR.get(r-2)) {
			ans = Math.min(ans, dist[map.get(new PII(r-2, x))]) ;
		}

		for(int x : litC.get(c-1)) {
			ans = Math.min(ans, dist[map.get(new PII(x, c-1))]) ;
		}

		for(int x : litC.get(c-2)) {
			ans = Math.min(ans, dist[map.get(new PII(x, c-2))]) ;
		}

		System.out.println(ans == Integer.MAX_VALUE ? -1 : ans + 1);

	}

	private static void relaxCol(int curCol, PriorityQueue<Triple> pq, Triple cur) {

		if(curCol < 0 || curCol >= c || usedCol[curCol]) {
			return;
		}

		for(int rr : litC.get(curCol)) {

			if(cur.dist + 1 < dist[map.get(new PII(rr, curCol))]) {
				dist[map.get(new PII(rr, curCol))] = cur.dist + 1;
				pq.offer(new Triple(rr, curCol, cur.dist+1));
			}
		}

		usedCol[curCol] = true;

	}

	private static void relaxRow(int curRow, PriorityQueue<Triple> pq, Triple cur) {

		if(curRow < 0 || curRow >= r || usedRow[curRow]) {
			return;
		}

		for(int cc : litR.get(curRow)) {

			if(cur.dist + 1 < dist[map.get(new PII(curRow, cc))]) {
				dist[map.get(new PII(curRow, cc))] = cur.dist + 1;
				pq.offer(new Triple(curRow, cc, cur.dist+1));
			}
		}

		usedRow[curRow] = true;

	}

}

class PII extends Point {

	public PII(int rr, int cc) {
		super(rr, cc);
	}

	@Override
	public int hashCode() {
		return  (31*x) + (31*y);
	}
}
class Triple {
	public Triple(int x, int y, int dist) {
		super();
		this.x = x;
		this.y = y;
		this.dist = dist;
	}

	int x, y, dist;

}


import java.io.*;
import java.util.*;

public class Main {
    static myScanner sc;
    static PrintWriter pw;

    public static void main(String[] args) throws IOException {
        //setInAndOutPutFromFile("ladder");
        setDefaultInAndOutPut();

        int numberOfTests = 1;
        for (int test = 1; test <= numberOfTests; test++) {
            solve();
            pw.flush();
        }

        pw.close();
    }

    static void setDefaultInAndOutPut() {
        sc = new myScanner(new BufferedReader(new InputStreamReader(System.in)));
        pw = new PrintWriter(System.out);
    }

    static void setInAndOutPutFromFile(String s) throws IOException {
        sc = new myScanner(new BufferedReader(new FileReader(new File(s + ".in"))));
        pw = new PrintWriter(new File(s + ".out"));
    }

    static int n, m;
    static int[] x, y;
    static int[] min;
    static int INF = 10000000;

    static void solve() {
        n = sc.nextInt();
        m = sc.nextInt();
        int k = sc.nextInt();
        x = new int[k];
        y = new int[k];
        min = new int[k];
        boolean[] used = new boolean[k];
        for (int i = 1; i < k; i++) min[i] = INF;
        for (int i = 0; i < k; i++) {
            x[i] = sc.nextInt();
            y[i] = sc.nextInt();
            if (x[i] == 1 && y[i] == 1) min[i] = 0;
        }
        int ans = INF;
        for (int i = 0; i < k; i++) {
            int v = -1;
            for (int j = 0; j < k; j++) {
                if (!used[j] && (v == -1 || min[j] < min[v])) v = j;
            }
            if (v == -1) break;
            used[v] = true;
            if ((n-x[v]<=1 || m-y[v]<=1) && min[v] < ans) {
                ans = Math.min(min[v] + 1,ans);
                if ((x[v] == n && y[v] == m))ans = Math.min(min[v],ans);
            }
            for (int j = 0; j < k; j++) {
                if (!used[j]){
                    int to = INF;

                    if (Math.abs(x[v]-x[j])<=1){
                        if (Math.abs(y[v]-y[j])<=1 && Math.abs(x[v]-x[j])==0)to=Math.min(min[v],to);else to=Math.min(min[v]+1,to);
                    }
                    if (Math.abs(y[v]-y[j])<=1){
                        if (Math.abs(x[v]-x[j])<=1 && Math.abs(y[v]-y[j])==0)to=Math.min(min[v],to);else to=Math.min(min[v]+1,to);
                    }
                    if (Math.abs(x[v]-x[j])==2 || Math.abs(y[v]-y[j])==2){
                        to=Math.min(min[v]+1,to);
                    }
                    min[j]=Math.min(to,min[j]);
                }
            }
        }
        pw.print(ans < INF ? ans : -1);
    }
}

class myScanner {
    private char[] buffer = new char[1 << 8];
    private int pos = 1;

    private BufferedReader reader;

    public myScanner(BufferedReader reader) {
        this.reader = reader;
    }

    public boolean hasNext() {
        return pos > 0;
    }

    private void loadBuffer() {
        pos = 0;
        try {
            for (int i; (i = reader.read()) != -1; ) {
                char c = (char) i;
                if (c != ' ' && c != '\n' && c != '\t' && c != '\r' && c != '\f') {
                    if (pos == buffer.length) buffer = Arrays.copyOf(buffer, 2 * pos);
                    buffer[pos++] = c;
                } else if (pos != 0) break;
            }
        } catch (IOException e) {
            throw new UncheckedIOException(e);
        }
    }

    public String current() {
        return String.copyValueOf(buffer, 0, pos);
    }

    public String next() {
        loadBuffer();
        return current();
    }

    public String nextLine() {
        try {
            return reader.readLine();
        } catch (IOException e) {
            throw new UncheckedIOException(e);
        }
    }

    public int nextInt() {
        return nextInt(10);
    }

    public long nextLong() {
        return nextLong(10);
    }

    public int nextInt(int radix) {
        loadBuffer();
        int result = 0;
        int i = buffer[0] == '-' || buffer[0] == '+' ? 1 : 0;
        for (checkValidNumber(pos > i); i < pos; i++) {
            int digit = buffer[i] - '0';
            checkValidNumber(0 <= digit && digit <= radix - 1);
            result = result * radix + digit;
        }
        return buffer[0] == '-' ? -result : result;
    }

    public long nextLong(int radix) {
        loadBuffer();
        long result = 0;
        int i = buffer[0] == '-' || buffer[0] == '+' ? 1 : 0;
        for (checkValidNumber(pos > i); i < pos; i++) {
            int digit = buffer[i] - '0';
            checkValidNumber(0 <= digit && digit <= radix - 1);
            result = result * radix + digit;
        }
        return buffer[0] == '-' ? -result : result;
    }

    public double nextDouble() {
        loadBuffer();
        long result = 0;
        int i = buffer[0] == '-' || buffer[0] == '+' ? 1 : 0;
        long round = 1;
        final int radix = 10;
        boolean hasPoint = false;
        for (checkValidNumber(pos > i); i < pos; i++) {
            int digit = buffer[i] - '0';
            checkValidNumber((0 <= digit && digit <= radix - 1) || (!hasPoint && digit == -2));
            if (digit == -2) hasPoint = true;
            else {
                if (hasPoint) round *= radix;
                result = result * radix + digit;
            }

        }
        return buffer[0] == '-' ? -result / (1.0 * round) : result / (1.0 * round);
    }

    private void checkValidNumber(boolean condition) {
        if (!condition) throw new NumberFormatException(current());
    }
}


import java.io.*;
import java.util.Arrays;

public class Main {
    static myScanner sc;
    static PrintWriter pw;

    public static void main(String[] args) throws IOException {
        //setInAndOutPutFromFile("ladder");
        setDefaultInAndOutPut();

        int numberOfTests = 1;
        for (int test = 1; test <= numberOfTests; test++) {
            solve();
            pw.flush();
        }

        pw.close();
    }

    static void setDefaultInAndOutPut() {
        sc = new myScanner(new BufferedReader(new InputStreamReader(System.in)));
        pw = new PrintWriter(System.out);
    }

    static void setInAndOutPutFromFile(String s) throws IOException {
        sc = new myScanner(new BufferedReader(new FileReader(new File(s + ".in"))));
        pw = new PrintWriter(new File(s + ".out"));
    }

    static int n, m;
    static int[] x, y;
    static int[] min;
    static int INF = 10000000;

    static void solve() {
        n = sc.nextInt();
        m = sc.nextInt();
        int k = sc.nextInt();
        x = new int[k];
        y = new int[k];
        min = new int[k];
        boolean[] used = new boolean[k];
        for (int i = 1; i < k; i++) min[i] = INF;
        for (int i = 0; i < k; i++) {
            x[i] = sc.nextInt();
            y[i] = sc.nextInt();
            if (x[i] == 1 && y[i] == 1) min[i] = 0;
        }
        int ans = INF;
        for (int i = 0; i < k; i++) {
            int v = -1;
            for (int j = 0; j < k; j++) {
                if (!used[j] && (v == -1 || min[j] < min[v])) v = j;
            }
            if (v == -1) break;
            used[v] = true;
            if ((x[v] == n || y[v] == m) && min[v] < ans) {
                ans = Math.min(min[v] + 1,ans);
                if ((x[v] == n && y[v] == m))ans = Math.min(min[v],ans);
            }
            for (int j = 0; j < k; j++) {
                if (!used[j]){
                    int to = INF;
                    if (x[v]==x[j]){
                        if (Math.abs(y[v]-y[j])<=1)to=min[v];else to=min[v]+1;
                    }else if (y[v]==y[j]){
                        if (Math.abs(x[v]-x[j])<=1)to=min[v];else to=min[v]+1;
                    }
                    min[j]=Math.min(to,min[j]);
                }
            }
        }
        pw.print(ans < INF ? ans : -1);
    }
}

class myScanner {
    private char[] buffer = new char[1 << 8];
    private int pos = 1;

    private BufferedReader reader;

    public myScanner(BufferedReader reader) {
        this.reader = reader;
    }

    public boolean hasNext() {
        return pos > 0;
    }

    private void loadBuffer() {
        pos = 0;
        try {
            for (int i; (i = reader.read()) != -1; ) {
                char c = (char) i;
                if (c != ' ' && c != '\n' && c != '\t' && c != '\r' && c != '\f') {
                    if (pos == buffer.length) buffer = Arrays.copyOf(buffer, 2 * pos);
                    buffer[pos++] = c;
                } else if (pos != 0) break;
            }
        } catch (IOException e) {
            throw new UncheckedIOException(e);
        }
    }

    public String current() {
        return String.copyValueOf(buffer, 0, pos);
    }

    public String next() {
        loadBuffer();
        return current();
    }

    public String nextLine() {
        try {
            return reader.readLine();
        } catch (IOException e) {
            throw new UncheckedIOException(e);
        }
    }

    public int nextInt() {
        return nextInt(10);
    }

    public long nextLong() {
        return nextLong(10);
    }

    public int nextInt(int radix) {
        loadBuffer();
        int result = 0;
        int i = buffer[0] == '-' || buffer[0] == '+' ? 1 : 0;
        for (checkValidNumber(pos > i); i < pos; i++) {
            int digit = buffer[i] - '0';
            checkValidNumber(0 <= digit && digit <= radix - 1);
            result = result * radix + digit;
        }
        return buffer[0] == '-' ? -result : result;
    }

    public long nextLong(int radix) {
        loadBuffer();
        long result = 0;
        int i = buffer[0] == '-' || buffer[0] == '+' ? 1 : 0;
        for (checkValidNumber(pos > i); i < pos; i++) {
            int digit = buffer[i] - '0';
            checkValidNumber(0 <= digit && digit <= radix - 1);
            result = result * radix + digit;
        }
        return buffer[0] == '-' ? -result : result;
    }

    public double nextDouble() {
        loadBuffer();
        long result = 0;
        int i = buffer[0] == '-' || buffer[0] == '+' ? 1 : 0;
        long round = 1;
        final int radix = 10;
        boolean hasPoint = false;
        for (checkValidNumber(pos > i); i < pos; i++) {
            int digit = buffer[i] - '0';
            checkValidNumber((0 <= digit && digit <= radix - 1) || (!hasPoint && digit == -2));
            if (digit == -2) hasPoint = true;
            else {
                if (hasPoint) round *= radix;
                result = result * radix + digit;
            }

        }
        return buffer[0] == '-' ? -result / (1.0 * round) : result / (1.0 * round);
    }

    private void checkValidNumber(boolean condition) {
        if (!condition) throw new NumberFormatException(current());
    }
}


import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.*;

/**
 * @author Don Li
 */
public class OkabeCity {

    int N = (int) 1e4;
    int INF = (int) 1e9;

    int[] dx = new int[]{-1, 0, 0, 1};
    int[] dy = new int[]{0, -1, 1, 0};

    int n, m, k;
    int[] r = new int[N], c = new int[N];

    Map<Integer, Integer> map = new HashMap<>();

    int nc = 0;
    int[] mark = new int[N];

    void solve() {
        n = in.nextInt();
        m = in.nextInt();
        k = in.nextInt();

        int s = -1;
        for (int i = 0; i < k; i++) {
            r[i] = in.nextInt() - 1;
            c[i] = in.nextInt() - 1;
            if (r[i] == 0 && c[i] == 0) s = i;
            map.put(r[i] * N + c[i], i);
        }

        Arrays.fill(mark, -1);
        for (int i = 0; i < k; i++) {
            if (mark[i] < 0) {
                mark[i] = nc++;
                dfs(i);
            }
        }
        int[] cnt = new int[nc];
        for (int i = 0; i < k; i++) cnt[mark[i]]++;
        int[][] g = new int[nc][];
        for (int i = 0; i < nc; i++) g[i] = new int[cnt[i]];
        for (int i = 0; i < k; i++) g[mark[i]][--cnt[mark[i]]] = i;

        int[] cnt_row = new int[n], cnt_col = new int[m];
        for (int i = 0; i < k; i++) {
            cnt_row[r[i]]++;
            cnt_col[c[i]]++;
        }
        int[][] rows = new int[n][];
        int[][] cols = new int[m][];
        for (int i = 0; i < n; i++) rows[i] = new int[cnt_row[i]];
        for (int j = 0; j < m; j++) cols[j] = new int[cnt_col[j]];
        for (int i = 0; i < k; i++) {
            rows[r[i]][--cnt_row[r[i]]] = i;
            cols[c[i]][--cnt_col[c[i]]] = i;
        }

        int[] dp = new int[k];
        Arrays.fill(dp, INF);
        dp[s] = 0;
        Queue<int[]> qu = new ArrayDeque<>(k);
        qu.offer(new int[]{dp[s], s});
        int[] mark_row = new int[n];
        int[] mark_col = new int[m];
        int[] mark_color = new int[nc];
        while (!qu.isEmpty()) {
            int[] t = qu.poll();
            int d = t[0], u = t[1];
            if (d > dp[u]) continue;

            if (mark_color[mark[u]] == 0) {
                for (int v : g[mark[u]]) {
                    dp[v] = dp[u];
                    qu.offer(new int[]{dp[v], v});
                }
                mark_color[mark[u]] = 1;
            }

            int x = r[u], y = c[u];
            for (int i = 0; i < 3; i++) {
                if (x + i < n && mark_row[x + i] == 0) {
                    for (int v : rows[x + i]) {
                        if (dp[v] > dp[u] + 1) {
                            dp[v] = dp[u] + 1;
                            qu.offer(new int[]{dp[v], v});
                        }
                    }
                    mark_row[x + i] = 1;
                }
                if (y + i < m && mark_col[y + i] == 0) {
                    for (int v : cols[y + i]) {
                        if (dp[v] > dp[u] + 1) {
                            dp[v] = dp[u] + 1;
                            qu.offer(new int[]{dp[v], v});
                        }
                    }
                    mark_col[y + i] = 1;
                }
            }
        }

        int ans = INF;
        for (int i = 0; i < k; i++) {
            int dx = n - 1 - r[i], dy = m - 1 - c[i];
            if (dx <= 1 || dy <= 1) {
                if (dx == 0 && dy == 0) ans = Math.min(ans, dp[i]);
                else ans = Math.min(ans, dp[i] + 1);
            }
        }
        if (ans == INF) ans = -1;
        out.println(ans);
    }

    void dfs(int u) {
        int x = r[u], y = c[u];
        for (int i = 0; i < 4; i++) {
            int nx = x + dx[i], ny = y + dy[i];
            if (nx >= 0 && nx < n && ny >= 0 && ny < m) {
                int v = map.getOrDefault(nx * N + ny, -1);
                if (v >= 0 && mark[v] < 0) {
                    mark[v] = mark[u];
                    dfs(v);
                }
            }
        }
    }

    public static void main(String[] args) {
        in = new FastScanner(new BufferedReader(new InputStreamReader(System.in)));
        out = new PrintWriter(System.out);
        new OkabeCity().solve();
        out.close();
    }

    static FastScanner in;
    static PrintWriter out;

    static class FastScanner {
        BufferedReader in;
        StringTokenizer st;

        public FastScanner(BufferedReader in) {
            this.in = in;
        }

        public String nextToken() {
            while (st == null || !st.hasMoreTokens()) {
                try {
                    st = new StringTokenizer(in.readLine());
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            return st.nextToken();
        }

        public int nextInt() {
            return Integer.parseInt(nextToken());
        }

        public long nextLong() {
            return Long.parseLong(nextToken());
        }

        public double nextDouble() {
            return Double.parseDouble(nextToken());
        }
    }
}


import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.*;

/**
 * @author Don Li
 */
public class OkabeCity2 {

    int N = (int) 1e4;
    int INF = (int) 1e9;

    int[] dx = new int[]{-1, 0, 0, 1};
    int[] dy = new int[]{0, -1, 1, 0};

    int n, m, k;
    int[] r = new int[N], c = new int[N];

    Map<Integer, Integer> map = new HashMap<>();

    int nc = 0;
    int[] mark = new int[N];

    void solve() {
        n = in.nextInt();
        m = in.nextInt();
        k = in.nextInt();

        int s = -1;
        for (int i = 0; i < k; i++) {
            r[i] = in.nextInt() - 1;
            c[i] = in.nextInt() - 1;
            if (r[i] == 0 && c[i] == 0) s = i;
            map.put(r[i] * N + c[i], i);
        }

        Arrays.fill(mark, -1);
        for (int i = 0; i < k; i++) {
            if (mark[i] < 0) {
                mark[i] = nc++;
                dfs(i);
            }
        }
        int[] cnt = new int[nc];
        for (int i = 0; i < k; i++) cnt[mark[i]]++;
        int[][] g = new int[nc][];
        for (int i = 0; i < nc; i++) g[i] = new int[cnt[i]];
        for (int i = 0; i < k; i++) g[mark[i]][--cnt[mark[i]]] = i;

        int[] cnt_row = new int[n], cnt_col = new int[m];
        for (int i = 0; i < k; i++) {
            cnt_row[r[i]]++;
            cnt_col[c[i]]++;
        }
        int[][] rows = new int[n][];
        int[][] cols = new int[m][];
        for (int i = 0; i < n; i++) rows[i] = new int[cnt_row[i]];
        for (int j = 0; j < m; j++) cols[j] = new int[cnt_col[j]];
        for (int i = 0; i < k; i++) {
            rows[r[i]][--cnt_row[r[i]]] = i;
            cols[c[i]][--cnt_col[c[i]]] = i;
        }

        int[] dp = new int[k];
        Arrays.fill(dp, INF);

        int[] mark_row = new int[n];
        int[] mark_col = new int[m];
        int[] mark_com = new int[nc];

        dp[s] = 0;
        Deque<Integer> qu = new ArrayDeque<>(k);
        qu.offer(s);
        while (!qu.isEmpty()) {
            int u = qu.poll();
            if (mark_com[mark[u]] == 0) {
                for (int v : g[mark[u]]) {
                    if (dp[v] > dp[u]) {
                        dp[v] = dp[u];
                        qu.offerFirst(v);
                    }
                }
                mark_com[mark[u]] = 1;
            }
            int x = r[u], y = c[u];
            for (int i = -2; i <= 2; i++) {
                if (x + i >= 0 && x + i < n && mark_row[x + i] == 0) {
                    for (int v : rows[x + i]) {
                        if (dp[v] > dp[u] + 1) {
                            dp[v] = dp[u] + 1;
                            qu.offerLast(v);
                        }
                    }
                    mark_row[x + i] = 1;
                }
                if (y + i >= 0 && y + i < m && mark_col[y + i] == 0) {
                    for (int v : cols[y + i]) {
                        if (dp[v] > dp[u] + 1) {
                            dp[v] = dp[u] + 1;
                            qu.offerLast(v);
                        }
                    }
                    mark_col[y + i] = 1;
                }
            }
        }

        int ans = INF;
        for (int i = 0; i < k; i++) {
            int dx = n - 1 - r[i], dy = m - 1 - c[i];
            if (dx <= 1 || dy <= 1) {
                if (dx == 0 && dy == 0) ans = Math.min(ans, dp[i]);
                else ans = Math.min(ans, dp[i] + 1);
            }
        }
        if (ans == INF) ans = -1;
        out.println(ans);
    }

    void dfs(int u) {
        int x = r[u], y = c[u];
        for (int i = 0; i < 4; i++) {
            int nx = x + dx[i], ny = y + dy[i];
            if (nx >= 0 && nx < n && ny >= 0 && ny < m) {
                int v = map.getOrDefault(nx * N + ny, -1);
                if (v >= 0 && mark[v] < 0) {
                    mark[v] = mark[u];
                    dfs(v);
                }
            }
        }
    }

    public static void main(String[] args) {
        in = new FastScanner(new BufferedReader(new InputStreamReader(System.in)));
        out = new PrintWriter(System.out);
        new OkabeCity2().solve();
        out.close();
    }

    static FastScanner in;
    static PrintWriter out;

    static class FastScanner {
        BufferedReader in;
        StringTokenizer st;

        public FastScanner(BufferedReader in) {
            this.in = in;
        }

        public String nextToken() {
            while (st == null || !st.hasMoreTokens()) {
                try {
                    st = new StringTokenizer(in.readLine());
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            return st.nextToken();
        }

        public int nextInt() {
            return Integer.parseInt(nextToken());
        }

        public long nextLong() {
            return Long.parseLong(nextToken());
        }

        public double nextDouble() {
            return Double.parseDouble(nextToken());
        }
    }
}


import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.*;

/**
 * @author Don Li
 */
public class OkabeCity {

    int N = (int) 1e4;
    int INF = (int) 1e9;

    int[] dx = new int[]{-1, 0, 0, 1};
    int[] dy = new int[]{0, -1, 1, 0};

    int n, m, k;
    int[] r = new int[N], c = new int[N];

    Map<Integer, Integer> map = new HashMap<>();

    int nc = 0;
    int[] mark = new int[N];

    void solve() {
        n = in.nextInt();
        m = in.nextInt();
        k = in.nextInt();

        int s = -1;
        for (int i = 0; i < k; i++) {
            r[i] = in.nextInt() - 1;
            c[i] = in.nextInt() - 1;
            if (r[i] == 0 && c[i] == 0) s = i;
            map.put(r[i] * N + c[i], i);
        }

        Arrays.fill(mark, -1);
        for (int i = 0; i < k; i++) {
            if (mark[i] < 0) {
                mark[i] = nc++;
                dfs(i);
            }
        }
        int[] cnt = new int[nc];
        for (int i = 0; i < k; i++) cnt[mark[i]]++;
        int[][] g = new int[nc][];
        for (int i = 0; i < nc; i++) g[i] = new int[cnt[i]];
        for (int i = 0; i < k; i++) g[mark[i]][--cnt[mark[i]]] = i;

        int[] cnt_row = new int[n], cnt_col = new int[m];
        for (int i = 0; i < k; i++) {
            cnt_row[r[i]]++;
            cnt_col[c[i]]++;
        }
        int[][] rows = new int[n][];
        int[][] cols = new int[m][];
        for (int i = 0; i < n; i++) rows[i] = new int[cnt_row[i]];
        for (int j = 0; j < m; j++) cols[j] = new int[cnt_col[j]];
        for (int i = 0; i < k; i++) {
            rows[r[i]][--cnt_row[r[i]]] = i;
            cols[c[i]][--cnt_col[c[i]]] = i;
        }

        int[] dp = new int[k];
        Arrays.fill(dp, INF);
        dp[s] = 0;
        Queue<int[]> qu = new PriorityQueue<>(Comparator.comparingInt(a -> a[0]));
        qu.offer(new int[]{dp[s], s});
        int[] mark_row = new int[n];
        int[] mark_col = new int[m];
        int[] mark_color = new int[nc];
        while (!qu.isEmpty()) {
            int[] t = qu.poll();
            int d = t[0], u = t[1];
            if (d > dp[u]) continue;

            if (mark_color[mark[u]] == 0) {
                for (int v : g[mark[u]]) {
                    dp[v] = dp[u];
                    qu.offer(new int[]{dp[v], v});
                }
                mark_color[mark[u]] = 1;
            }

            int x = r[u], y = c[u];
            for (int i = 0; i <= 2; i++) {
                if (x + i < n && mark_row[x + i] == 0) {
                    for (int v : rows[x + i]) {
                        if (dp[v] > dp[u] + 1) {
                            dp[v] = dp[u] + 1;
                            qu.offer(new int[]{dp[v], v});
                        }
                    }
                    mark_row[x + i] = 1;
                }
                if (y + i < m && mark_col[y + i] == 0) {
                    for (int v : cols[y + i]) {
                        if (dp[v] > dp[u] + 1) {
                            dp[v] = dp[u] + 1;
                            qu.offer(new int[]{dp[v], v});
                        }
                    }
                    mark_col[y + i] = 1;
                }
            }
        }

        int ans = INF;
        for (int i = 0; i < k; i++) {
            int dx = n - 1 - r[i], dy = m - 1 - c[i];
            if (dx <= 1 || dy <= 1) {
                if (dx == 0 && dy == 0) ans = Math.min(ans, dp[i]);
                else ans = Math.min(ans, dp[i] + 1);
            }
        }
        if (ans == INF) ans = -1;
        out.println(ans);
    }

    void dfs(int u) {
        int x = r[u], y = c[u];
        for (int i = 0; i < 4; i++) {
            int nx = x + dx[i], ny = y + dy[i];
            if (nx >= 0 && nx < n && ny >= 0 && ny < m) {
                int v = map.getOrDefault(nx * N + ny, -1);
                if (v >= 0 && mark[v] < 0) {
                    mark[v] = mark[u];
                    dfs(v);
                }
            }
        }
    }

    public static void main(String[] args) {
        in = new FastScanner(new BufferedReader(new InputStreamReader(System.in)));
        out = new PrintWriter(System.out);
        new OkabeCity().solve();
        out.close();
    }

    static FastScanner in;
    static PrintWriter out;

    static class FastScanner {
        BufferedReader in;
        StringTokenizer st;

        public FastScanner(BufferedReader in) {
            this.in = in;
        }

        public String nextToken() {
            while (st == null || !st.hasMoreTokens()) {
                try {
                    st = new StringTokenizer(in.readLine());
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            return st.nextToken();
        }

        public int nextInt() {
            return Integer.parseInt(nextToken());
        }

        public long nextLong() {
            return Long.parseLong(nextToken());
        }

        public double nextDouble() {
            return Double.parseDouble(nextToken());
        }
    }
}


import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.*;

/**
 * @author Don Li
 */
public class OkabeCity {

    int N = (int) 1e4;
    int INF = (int) 1e9;

    int[] dx = new int[]{-1, 0, 0, 1};
    int[] dy = new int[]{0, -1, 1, 0};

    int n, m, k;
    int[] r = new int[N], c = new int[N];

    Map<Integer, Integer> map = new HashMap<>();

    int nc = 0;
    int[] mark = new int[N];

    void solve() {
        n = in.nextInt();
        m = in.nextInt();
        k = in.nextInt();

        int s = -1;
        for (int i = 0; i < k; i++) {
            r[i] = in.nextInt() - 1;
            c[i] = in.nextInt() - 1;
            if (r[i] == 0 && c[i] == 0) s = i;
            map.put(r[i] * N + c[i], i);
        }

        Arrays.fill(mark, -1);
        for (int i = 0; i < k; i++) {
            if (mark[i] < 0) {
                mark[i] = nc++;
                dfs(i);
            }
        }
        int[] cnt = new int[nc];
        for (int i = 0; i < k; i++) cnt[mark[i]]++;
        int[][] g = new int[nc][];
        for (int i = 0; i < nc; i++) g[i] = new int[cnt[i]];
        for (int i = 0; i < k; i++) g[mark[i]][--cnt[mark[i]]] = i;

        int[] cnt_row = new int[n], cnt_col = new int[m];
        for (int i = 0; i < k; i++) {
            cnt_row[r[i]]++;
            cnt_col[c[i]]++;
        }
        int[][] rows = new int[n][];
        int[][] cols = new int[m][];
        for (int i = 0; i < n; i++) rows[i] = new int[cnt_row[i]];
        for (int j = 0; j < m; j++) cols[j] = new int[cnt_col[j]];
        for (int i = 0; i < k; i++) {
            rows[r[i]][--cnt_row[r[i]]] = i;
            cols[c[i]][--cnt_col[c[i]]] = i;
        }

        int[] dp = new int[k];
        Arrays.fill(dp, INF);
        dp[s] = 0;
        Queue<int[]> qu = new PriorityQueue<>(Comparator.comparingInt(a -> a[0]));
        qu.offer(new int[]{dp[s], s});
        int[] mark_row = new int[n];
        int[] mark_col = new int[m];
        int[] mark_color = new int[nc];
        while (!qu.isEmpty()) {
            int[] t = qu.poll();
            int d = t[0], u = t[1];
            if (d > dp[u]) continue;

            if (mark_color[mark[u]] == 0) {
                for (int v : g[mark[u]]) {
                    dp[v] = dp[u];
                    qu.offer(new int[]{dp[v], v});
                }
                mark_color[mark[u]] = 1;
            }

            int x = r[u], y = c[u];
            for (int i = -2; i <= 2; i++) {
                if (x + i < n && mark_row[x + i] == 0) {
                    for (int v : rows[x + i]) {
                        if (dp[v] > dp[u] + 1) {
                            dp[v] = dp[u] + 1;
                            qu.offer(new int[]{dp[v], v});
                        }
                    }
                    mark_row[x + i] = 1;
                }
                if (y + i < m && mark_col[y + i] == 0) {
                    for (int v : cols[y + i]) {
                        if (dp[v] > dp[u] + 1) {
                            dp[v] = dp[u] + 1;
                            qu.offer(new int[]{dp[v], v});
                        }
                    }
                    mark_col[y + i] = 1;
                }
            }
        }

        int ans = INF;
        for (int i = 0; i < k; i++) {
            int dx = n - 1 - r[i], dy = m - 1 - c[i];
            if (dx <= 1 || dy <= 1) {
                if (dx == 0 && dy == 0) ans = Math.min(ans, dp[i]);
                else ans = Math.min(ans, dp[i] + 1);
            }
        }
        if (ans == INF) ans = -1;
        out.println(ans);
    }

    void dfs(int u) {
        int x = r[u], y = c[u];
        for (int i = 0; i < 4; i++) {
            int nx = x + dx[i], ny = y + dy[i];
            if (nx >= 0 && nx < n && ny >= 0 && ny < m) {
                int v = map.getOrDefault(nx * N + ny, -1);
                if (v >= 0 && mark[v] < 0) {
                    mark[v] = mark[u];
                    dfs(v);
                }
            }
        }
    }

    public static void main(String[] args) {
        in = new FastScanner(new BufferedReader(new InputStreamReader(System.in)));
        out = new PrintWriter(System.out);
        new OkabeCity().solve();
        out.close();
    }

    static FastScanner in;
    static PrintWriter out;

    static class FastScanner {
        BufferedReader in;
        StringTokenizer st;

        public FastScanner(BufferedReader in) {
            this.in = in;
        }

        public String nextToken() {
            while (st == null || !st.hasMoreTokens()) {
                try {
                    st = new StringTokenizer(in.readLine());
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            return st.nextToken();
        }

        public int nextInt() {
            return Integer.parseInt(nextToken());
        }

        public long nextLong() {
            return Long.parseLong(nextToken());
        }

        public double nextDouble() {
            return Double.parseDouble(nextToken());
        }
    }
}


import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.*;

/**
 * @author Don Li
 */
public class OkabeCity {

    int N = (int) 1e4;
    int INF = (int) 1e9;

    int[] dx = new int[]{-1, 0, 0, 1};
    int[] dy = new int[]{0, -1, 1, 0};

    void solve() {
        int n = in.nextInt(), m = in.nextInt(), k = in.nextInt();

        int s = -1;
        int[] r = new int[k], c = new int[k];
        Map<Integer, Integer> map = new HashMap<>();
        for (int i = 0; i < k; i++) {
            r[i] = in.nextInt() - 1;
            c[i] = in.nextInt() - 1;
            if (r[i] == 0 && c[i] == 0) s = i;
            map.put(r[i] * N + c[i], i);
        }

        int[] cnt_row = new int[n], cnt_col = new int[m];
        for (int i = 0; i < k; i++) {
            cnt_row[r[i]]++;
            cnt_col[c[i]]++;
        }
        int[][] rows = new int[n][];
        int[][] cols = new int[m][];
        for (int i = 0; i < n; i++) rows[i] = new int[cnt_row[i]];
        for (int j = 0; j < m; j++) cols[j] = new int[cnt_col[j]];
        for (int i = 0; i < k; i++) {
            rows[r[i]][--cnt_row[r[i]]] = i;
            cols[c[i]][--cnt_col[c[i]]] = i;
        }

        int[] dp = new int[k];
        Arrays.fill(dp, INF);
        dp[s] = 0;
        Queue<int[]> qu = new ArrayDeque<>(k);
        qu.offer(new int[]{dp[s], s});
        int[] mark_row = new int[n];
        int[] mark_col = new int[m];
        while (!qu.isEmpty()) {
            int[] t = qu.poll();
            int d = t[0], u = t[1];
            if (d > dp[u]) continue;
            int x = r[u], y = c[u];
            for (int i = 0; i < 4; i++) {
                int nx = x + dx[i], ny = y + dy[i];
                if (nx >= 0 && nx < n && ny >= 0 && ny < m) {
                    int v = map.getOrDefault(nx * N + ny, -1);
                    if (v >= 0 && dp[v] > dp[u]) {
                        dp[v] = dp[u];
                        qu.offer(new int[]{dp[v], v});
                    }
                }
            }
            for (int i = 0; i < 3; i++) {
                if (x + i < n && mark_row[x + i] == 0) {
                    for (int v : rows[x + i]) {
                        if (dp[v] > dp[u] + 1) {
                            dp[v] = dp[u] + 1;
                            qu.offer(new int[]{dp[v], v});
                        }
                    }
                    mark_row[x + i] = 1;
                }
                if (y + i < m && mark_col[y + i] == 0) {
                    for (int v : cols[y + i]) {
                        if (dp[v] > dp[u] + 1) {
                            dp[v] = dp[u] + 1;
                            qu.offer(new int[]{dp[v], v});
                        }
                    }
                    mark_col[y + i] = 1;
                }
            }
        }

        int ans = INF;
        for (int i = 0; i < k; i++) {
            int dx = n - 1 - r[i], dy = m - 1 - c[i];
            if (dx <= 1 || dy <= 1) {
                if (dx == 0 && dy == 0) ans = Math.min(ans, dp[i]);
                else ans = Math.min(ans, dp[i] + 1);
            }
        }
        if (ans == INF) ans = -1;
        out.println(ans);
    }

    public static void main(String[] args) {
        in = new FastScanner(new BufferedReader(new InputStreamReader(System.in)));
        out = new PrintWriter(System.out);
        new OkabeCity().solve();
        out.close();
    }

    static FastScanner in;
    static PrintWriter out;

    static class FastScanner {
        BufferedReader in;
        StringTokenizer st;

        public FastScanner(BufferedReader in) {
            this.in = in;
        }

        public String nextToken() {
            while (st == null || !st.hasMoreTokens()) {
                try {
                    st = new StringTokenizer(in.readLine());
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            return st.nextToken();
        }

        public int nextInt() {
            return Integer.parseInt(nextToken());
        }

        public long nextLong() {
            return Long.parseLong(nextToken());
        }

        public double nextDouble() {
            return Double.parseDouble(nextToken());
        }
    }
}


import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.*;

/**
 * @author Don Li
 */
public class OkabeCity {

    int N = (int) 1e4;
    int INF = (int) 1e9;

    int[] dx = new int[]{-1, 0, 0, 1};
    int[] dy = new int[]{0, -1, 1, 0};

    int n, m, k;
    int[] r = new int[N], c = new int[N];

    Map<Integer, Integer> map = new HashMap<>();

    int nc = 0;
    int[] mark = new int[N];

    void solve() {
        n = in.nextInt();
        m = in.nextInt();
        k = in.nextInt();

        int s = -1;
        for (int i = 0; i < k; i++) {
            r[i] = in.nextInt() - 1;
            c[i] = in.nextInt() - 1;
            if (r[i] == 0 && c[i] == 0) s = i;
            map.put(r[i] * N + c[i], i);
        }

        Arrays.fill(mark, -1);
        for (int i = 0; i < k; i++) {
            if (mark[i] < 0) {
                mark[i] = nc++;
                dfs(i);
            }
        }
        int[] cnt = new int[nc];
        for (int i = 0; i < k; i++) cnt[mark[i]]++;
        int[][] g = new int[nc][];
        for (int i = 0; i < nc; i++) g[i] = new int[cnt[i]];
        for (int i = 0; i < k; i++) g[mark[i]][--cnt[mark[i]]] = i;

        int[] cnt_row = new int[n], cnt_col = new int[m];
        for (int i = 0; i < k; i++) {
            cnt_row[r[i]]++;
            cnt_col[c[i]]++;
        }
        int[][] rows = new int[n][];
        int[][] cols = new int[m][];
        for (int i = 0; i < n; i++) rows[i] = new int[cnt_row[i]];
        for (int j = 0; j < m; j++) cols[j] = new int[cnt_col[j]];
        for (int i = 0; i < k; i++) {
            rows[r[i]][--cnt_row[r[i]]] = i;
            cols[c[i]][--cnt_col[c[i]]] = i;
        }

        int[] dp = new int[k];
        Arrays.fill(dp, INF);
        dp[s] = 0;
        Queue<int[]> qu = new PriorityQueue<>(Comparator.comparingInt(a -> a[0]));
        qu.offer(new int[]{dp[s], s});
        int[] mark_row = new int[n];
        int[] mark_col = new int[m];
        int[] mark_color = new int[nc];
        while (!qu.isEmpty()) {
            int[] t = qu.poll();
            int d = t[0], u = t[1];
            if (d > dp[u]) continue;

            if (mark_color[mark[u]] == 0) {
                for (int v : g[mark[u]]) {
                    dp[v] = dp[u];
                    qu.offer(new int[]{dp[v], v});
                }
                mark_color[mark[u]] = 1;
            }

            int x = r[u], y = c[u];
            for (int i = -2; i <= 2; i++) {
                if (x + i >= 0 && x + i < n && mark_row[x + i] == 0) {
                    for (int v : rows[x + i]) {
                        if (dp[v] > dp[u] + 1) {
                            dp[v] = dp[u] + 1;
                            qu.offer(new int[]{dp[v], v});
                        }
                    }
                    mark_row[x + i] = 1;
                }
                if (y + i >= 0 && y + i < m && mark_col[y + i] == 0) {
                    for (int v : cols[y + i]) {
                        if (dp[v] > dp[u] + 1) {
                            dp[v] = dp[u] + 1;
                            qu.offer(new int[]{dp[v], v});
                        }
                    }
                    mark_col[y + i] = 1;
                }
            }
        }

        int ans = INF;
        for (int i = 0; i < k; i++) {
            int dx = n - 1 - r[i], dy = m - 1 - c[i];
            if (dx <= 1 || dy <= 1) {
                if (dx == 0 && dy == 0) ans = Math.min(ans, dp[i]);
                else ans = Math.min(ans, dp[i] + 1);
            }
        }
        if (ans == INF) ans = -1;
        out.println(ans);
    }

    void dfs(int u) {
        int x = r[u], y = c[u];
        for (int i = 0; i < 4; i++) {
            int nx = x + dx[i], ny = y + dy[i];
            if (nx >= 0 && nx < n && ny >= 0 && ny < m) {
                int v = map.getOrDefault(nx * N + ny, -1);
                if (v >= 0 && mark[v] < 0) {
                    mark[v] = mark[u];
                    dfs(v);
                }
            }
        }
    }

    public static void main(String[] args) {
        in = new FastScanner(new BufferedReader(new InputStreamReader(System.in)));
        out = new PrintWriter(System.out);
        new OkabeCity().solve();
        out.close();
    }

    static FastScanner in;
    static PrintWriter out;

    static class FastScanner {
        BufferedReader in;
        StringTokenizer st;

        public FastScanner(BufferedReader in) {
            this.in = in;
        }

        public String nextToken() {
            while (st == null || !st.hasMoreTokens()) {
                try {
                    st = new StringTokenizer(in.readLine());
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            return st.nextToken();
        }

        public int nextInt() {
            return Integer.parseInt(nextToken());
        }

        public long nextLong() {
            return Long.parseLong(nextToken());
        }

        public double nextDouble() {
            return Double.parseDouble(nextToken());
        }
    }
}


import java.io.*;
import java.util.*;

public class CF821D {
	static final int INF = Integer.MAX_VALUE;
	static class V implements Comparable<V> {
		HashSet<V> set = new HashSet<>();
		int r, c, i, d = INF;
		V(int r, int c, int i) {
			this.r = r; this.c = c; this.i = i;
		}
		@Override public int compareTo(V v) {
			return d != v.d ? d - v.d : i - v.i;
		}
	}
	public static void main(String[] args) throws IOException {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		StringTokenizer st = new StringTokenizer(br.readLine());
		int n = Integer.parseInt(st.nextToken());
		int m = Integer.parseInt(st.nextToken());
		int k = Integer.parseInt(st.nextToken());
		V[] vv = new V[k];
		ArrayList<V>[] rr = new ArrayList[n];	// unchecked
		ArrayList<V>[] cc = new ArrayList[m];	// unchecked
		for (int r = 0; r < n; r++)
			rr[r] = new ArrayList<>();
		for (int c = 0; c < m; c++)
			cc[c] = new ArrayList<>();
		for (int i = 0; i < k; i++) {
			st = new StringTokenizer(br.readLine());
			int r = Integer.parseInt(st.nextToken()) - 1;
			int c = Integer.parseInt(st.nextToken()) - 1;
			V v = new V(r, c, i);
			vv[i] = v;
			rr[r].add(v);
			cc[c].add(v);
		}
		for (int i = 0; i < k; i++) {
			V u = vv[i];
			for (int r = u.r - 2; r <= u.r + 2; r++)
				if (r >= 0 && r < n)
					for (V v : rr[r])
						u.set.add(v);
			for (int c = u.c - 2; c <= u.c + 2; c++)
				if (c >= 0 && c < m)
					for (V v : rr[c])
						u.set.add(v);
		}
		TreeSet<V> queue = new TreeSet<>();
		for (V u : vv)
			if (u.r == 0 && u.c == 0) {
				u.d = 0;
				queue.add(u);
				break;
			}
		int min = INF;
		while (!queue.isEmpty()) {
			V u = queue.first();
			queue.remove(u);
			int r_ = Math.abs(n - 1 - u.r);
			int c_ = Math.abs(m - 1 - u.c);
			if (r_ == 0 && c_ == 0)
				min = Math.min(min, u.d);
			else if (r_ <= 1 || c_ <= 1)
				min = Math.min(min, u.d + 1);
			for (V v : u.set) {
				int d = u.d + (Math.abs(u.r - v.r) + Math.abs(u.c - v.c) == 1 ? 0 : 1);
				if (d < v.d) {
					queue.remove(v);
					v.d = d;
					queue.add(v);
				}
			}
		}
		System.out.println(min == INF ? -1 : min);
	}
}