#include <vector>
#include <algorithm>
#include <cmath>
#include <queue>
#include <string>
#include <set>
#include <climits>
#include <cstdio>
#include <iomanip>
#include <iterator>
#include <deque>
#include <map>
#include <cassert>
#include <ctime>

// #include <bits/stdc++.h>
#include <iostream>

using namespace std;

#define pb push_back
#define all(a) a.begin(), a.end()
#define rall(a) a.rbegin(), a.rend()
#define size(a) (int)a.size()
typedef long long ll;
typedef long double ld;
const int inf = 2e9;
const long double eps = 0.000001;
const long long mod = 1e9 + 7;
const long double PI = 3.14159265359;

template <class T>
struct MyVector : vector<T> {
	MyVector() : vector<T>() { }
	MyVector(int n) : vector<T>(n) { }
	T &operator [] (size_t i) {
		return vector<T>::at(i);
	}
};

struct Bohr {
	vector < int > nxt;
	bool leaf;
	Bohr() {
		nxt.resize(26, -1);
		leaf = false;
	}
};

vector < Bohr > t(1e6);
vector < vector < pair < int, int > > > s, rs;
vector < int > b;
vector < bool > isp;
int sz = 1;

int add(string s) {
	int it = 0;
	for (int i = 0; i < size(s); i++) {
		int a = s[i] - 'a';
		if (t[it].nxt[a] == -1) t[it].nxt[a] = sz, sz++;
		it = t[it].nxt[a];
	}

	t[it].leaf = true;
	return it;
}

int main() {
	ios_base::sync_with_stdio(false);
	cin.tie(nullptr);
	cout.tie(nullptr);
	#if _SLOVO
		freopen("input.txt", "r", stdin);
		freopen("output.txt", "w", stdout);
	#else
		//freopen(".in", "r", stdin);
		//freopen(".out", "w", stdout);
	#endif

	int k, n;
	cin >> k >> n;

	s.resize(1e6);
	rs.resize(1e6);
	b.resize(k);
	isp.resize(k, false);
	vector < vector < pair < int, int > > > p(1e6);

	for (int i = 0; i < k; i++) {
		string x;
		cin >> x;
		cin >> b[i];
		int idx;
		s[idx = add(x)].push_back({b[i], i});
		string rx = x;
		reverse(all(rx));
		if (rx == x) {
			s[idx].pop_back();
			p[idx].push_back({b[i], i});
			continue;
		}
		rs[add(rx)].push_back({b[i], i});
	}

	int ans = 0;
	vector < bool > was(k, false);

	for (int i = 0; i < 1e6; i++) {
		sort(all(s[i]));
		sort(all(rs[i]));
		while (!s[i].empty() && !rs[i].empty()) {
			int si = s[i].back().second, rsi = rs[i].back().second;
			if (was[si]) {
				s[i].pop_back();
				continue;
			}
			if (was[rsi]) {
				rs[i].pop_back();
				continue;
			}
			if (b[si] + b[rsi] > 0) {
				was[si] = true;
				was[rsi] = true;
				ans += b[si] + b[rsi];
			}
			s[i].pop_back();
			rs[i].pop_back();
		}
	}

	vector < pair < int, int > > last;

	for (int i = 0; i < 1e6; i++) {
		sort(all(p[i]));
		for (int j = size(p[i]) - 1; j >= 0; j--) {
			int m1 = p[i][j].second;
			if (j > 0) {
				int m2 = p[i][j - 1].second;
				if (b[m1] + b[m2] > 0 && b[m1] > 0 && b[m2] > 0) {
					ans += b[m1] + b[m2];
					was[m1] = true;
					was[m2] = true;
					j--;
					continue;
				}
			}
			if (b[m1] > 0) {
				last.push_back({b[m1], m1});
			}
		}
	}

	sort(rall(last));

	for (auto v : last) {
		if (!was[v.second]) {
			was[v.second] = true;
			ans += v.first;
			break;
		}
	}

	for (int i = 0; i < 1e6; i++) {
		sort(all(p[i]));
		for (int j = size(p[i]) - 1; j >= 0; j--) {
			while (j > 0 && was[p[i][j].second]) j--;
			if (j == 0 && was[p[i][j].second]) break;
			int m1 = p[i][j].second;
			if (j > 0) {
				while (j > 1 && was[p[i][j - 1].second]) j--;
				if (j == 1 && was[p[i][j - 1].second]) break;
				int m2 = p[i][j - 1].second;
				if (b[m1] + b[m2] > 0) {
					ans += b[m1] + b[m2];
					was[m1] = true;
					was[m2] = true;
					j--;
				}
			}
		}
	}

	cout << ans;

	return 0;
}


#include <vector>
#include <algorithm>
#include <cmath>
#include <queue>
#include <string>
#include <set>
#include <climits>
#include <cstdio>
#include <iomanip>
#include <iterator>
#include <deque>
#include <map>
#include <cassert>
#include <ctime>

// #include <bits/stdc++.h>
#include <iostream>

using namespace std;

#define pb push_back
#define all(a) a.begin(), a.end()
#define rall(a) a.rbegin(), a.rend()
#define size(a) (int)a.size()
typedef long long ll;
typedef long double ld;
const int inf = 2e9;
const long double eps = 0.000001;
const long long mod = 1e9 + 7;
const long double PI = 3.14159265359;

template <class T>
struct MyVector : vector<T> {
	MyVector() : vector<T>() { }
	MyVector(int n) : vector<T>(n) { }
	T &operator [] (size_t i) {
		return vector<T>::at(i);
	}
};

struct Bohr {
	vector < int > nxt;
	bool leaf;
	Bohr() {
		nxt.resize(26, -1);
		leaf = false;
	}
};

vector < Bohr > t(1e6);
vector < vector < pair < int, int > > > s, rs;
vector < int > b;
vector < bool > isp;
int sz = 1;

int add(string s) {
	int it = 0;
	for (int i = 0; i < size(s); i++) {
		int a = s[i] - 'a';
		if (t[it].nxt[a] == -1) t[it].nxt[a] = sz, sz++;
		it = t[it].nxt[a];
	}

	t[it].leaf = true;
	return it;
}

int main() {
	ios_base::sync_with_stdio(false);
	cin.tie(nullptr);
	cout.tie(nullptr);
	#if _SLOVO
		freopen("input.txt", "r", stdin);
		freopen("output.txt", "w", stdout);
	#else
		//freopen(".in", "r", stdin);
		//freopen(".out", "w", stdout);
	#endif

	int k, n;
	cin >> k >> n;

	s.resize(1e6);
	rs.resize(1e6);
	b.resize(k);
	isp.resize(k, false);
	vector < vector < pair < int, int > > > p(1e6);

	for (int i = 0; i < k; i++) {
		string x;
		cin >> x;
		cin >> b[i];
		int idx;
		s[idx = add(x)].push_back({b[i], i});
		string rx = x;
		reverse(all(rx));
		if (rx == x) {
			s[idx].pop_back();
			p[idx].push_back({b[i], i});
			continue;
		}
		rs[add(rx)].push_back({b[i], i});
	}

	int ans = 0;
	vector < bool > was(k, false);

	for (int i = 0; i < 1e6; i++) {
		sort(all(s[i]));
		sort(all(rs[i]));
		while (!s[i].empty() && !rs[i].empty()) {
			int si = s[i].back().second, rsi = rs[i].back().second;
			if (was[si]) {
				s[i].pop_back();
				continue;
			}
			if (was[rsi]) {
				rs[i].pop_back();
				continue;
			}
			if (b[si] + b[rsi] > 0) {
				was[si] = true;
				was[rsi] = true;
				ans += b[si] + b[rsi];
			}
			s[i].pop_back();
			rs[i].pop_back();
		}
	}

	vector < pair < int, int > > last;

	for (int i = 0; i < 1e6; i++) {
		sort(all(p[i]));
		for (int j = size(p[i]) - 1; j >= 0; j--) {
			int m1 = p[i][j].second;
			if (j > 0) {
				int m2 = p[i][j - 1].second;
				if (b[m1] + b[m2] > 0) {
					ans += b[m1] + b[m2];
					j--;
					if (b[m2] < 0) {
						last.push_back({-b[m2], m2});
					}
					continue;
				}
			}
			if (b[m1] > 0) {
				last.push_back({b[m1], m1});
			}
		}
	}

	sort(rall(last));

	for (auto v : last) {
		if (!was[v.second]) {
			ans += v.first;
			break;
		}
	}
	cout << ans;

	return 0;
}


#include <vector>
#include <algorithm>
#include <cmath>
#include <queue>
#include <string>
#include <set>
#include <climits>
#include <cstdio>
#include <iomanip>
#include <iterator>
#include <deque>
#include <map>
#include <cassert>
#include <ctime>

// #include <bits/stdc++.h>
#include <iostream>

using namespace std;

#define pb push_back
#define all(a) a.begin(), a.end()
#define rall(a) a.rbegin(), a.rend()
#define size(a) (int)a.size()
typedef long long ll;
typedef long double ld;
const int inf = 2e9;
const long double eps = 0.000001;
const long long mod = 1e9 + 7;
const long double PI = 3.14159265359;

template <class T>
struct MyVector : vector<T> {
	MyVector() : vector<T>() { }
	MyVector(int n) : vector<T>(n) { }
	T &operator [] (size_t i) {
		return vector<T>::at(i);
	}
};

struct Bohr {
	vector < int > nxt;
	bool leaf;
	Bohr() {
		nxt.resize(26, -1);
		leaf = false;
	}
};

vector < Bohr > t(1e6);
vector < vector < pair < int, int > > > s, rs;
vector < int > b;
vector < bool > isp;
int sz = 1;

int add(string s) {
	int it = 0;
	for (int i = 0; i < size(s); i++) {
		int a = s[i] - 'a';
		if (t[it].nxt[a] == -1) t[it].nxt[a] = sz, sz++;
		it = t[it].nxt[a];
	}

	t[it].leaf = true;
	return it;
}

int main() {
	ios_base::sync_with_stdio(false);
	cin.tie(nullptr);
	cout.tie(nullptr);
	#if _SLOVO
		freopen("input.txt", "r", stdin);
		freopen("output.txt", "w", stdout);
	#else
		//freopen(".in", "r", stdin);
		//freopen(".out", "w", stdout);
	#endif

	int k, n;
	cin >> k >> n;

	s.resize(1e6);
	rs.resize(1e6);
	b.resize(k);
	isp.resize(k, false);
	vector < vector < pair < int, int > > > p(1e6);

	for (int i = 0; i < k; i++) {
		string x;
		cin >> x;
		cin >> b[i];
		int idx;
		s[idx = add(x)].push_back({b[i], i});
		string rx = x;
		reverse(all(rx));
		if (rx == x) {
			s[idx].pop_back();
			p[idx].push_back({b[i], i});
			continue;
		}
		rs[add(rx)].push_back({b[i], i});
	}

	int ans = 0;
	vector < bool > was(k, false);

	for (int i = 0; i < 1e6; i++) {
		sort(all(s[i]));
		sort(all(rs[i]));
		while (!s[i].empty() && !rs[i].empty()) {
			int si = s[i].back().second, rsi = rs[i].back().second;
			if (was[si]) {
				s[i].pop_back();
				continue;
			}
			if (was[rsi]) {
				rs[i].pop_back();
				continue;
			}
			if (b[si] + b[rsi] > 0) {
				was[si] = true;
				was[rsi] = true;
				ans += b[si] + b[rsi];
			}
			s[i].pop_back();
			rs[i].pop_back();
		}
	}

	vector < pair < int, int > > last;

	for (int i = 0; i < 1e6; i++) {
		sort(all(p[i]));
		for (int j = size(p[i]) - 1; j >= 0; j--) {
			int m1 = p[i][j].second;
			if (j > 0) {
				int m2 = p[i][j - 1].second;
				if (b[m1] + b[m2] > 0) {
					ans += b[m1] + b[m2];
					was[m1] = true;
					was[m2] = true;
					j--;
					continue;
				}
				if (b[m2] < 0) {
					last.push_back({-b[m2], m2});
				}
			}
			if (b[m1] > 0) {
				last.push_back({b[m1], m1});
			}
		}
	}

	sort(rall(last));

	for (auto v : last) {
		if (!was[v.second]) {
			ans += v.first;
			break;
		}
	}
	cout << ans;

	return 0;
}


#include <vector>
#include <algorithm>
#include <cmath>
#include <queue>
#include <string>
#include <set>
#include <climits>
#include <cstdio>
#include <iomanip>
#include <iterator>
#include <deque>
#include <map>
#include <cassert>
#include <ctime>

// #include <bits/stdc++.h>
#include <iostream>

using namespace std;

#define pb push_back
#define all(a) a.begin(), a.end()
#define rall(a) a.rbegin(), a.rend()
#define size(a) (int)a.size()
typedef long long ll;
typedef long double ld;
const int inf = 2e9;
const long double eps = 0.000001;
const long long mod = 1e9 + 7;
const long double PI = 3.14159265359;

template <class T>
struct MyVector : vector<T> {
	MyVector() : vector<T>() { }
	MyVector(int n) : vector<T>(n) { }
	T &operator [] (size_t i) {
		return vector<T>::at(i);
	}
};

struct Bohr {
	vector < int > nxt;
	bool leaf;
	Bohr() {
		nxt.resize(26, -1);
		leaf = false;
	}
};

vector < Bohr > t(1e6);
vector < vector < pair < int, int > > > s, rs;
vector < int > b;
vector < bool > isp;
int sz = 1;

int add(string s) {
	int it = 0;
	for (int i = 0; i < size(s); i++) {
		int a = s[i] - 'a';
		if (t[it].nxt[a] == -1) t[it].nxt[a] = sz, sz++;
		it = t[it].nxt[a];
	}

	t[it].leaf = true;
	return it;
}

int main() {
	ios_base::sync_with_stdio(false);
	cin.tie(nullptr);
	cout.tie(nullptr);
	#if _SLOVO
		freopen("input.txt", "r", stdin);
		freopen("output.txt", "w", stdout);
	#else
		//freopen(".in", "r", stdin);
		//freopen(".out", "w", stdout);
	#endif

	int k, n;
	cin >> k >> n;

	s.resize(1e6);
	rs.resize(1e6);
	b.resize(k);
	isp.resize(k, false);
	vector < vector < pair < int, int > > > p(1e6);

	for (int i = 0; i < k; i++) {
		string x;
		cin >> x;
		cin >> b[i];
		int idx;
		s[idx = add(x)].push_back({b[i], i});
		string rx = x;
		reverse(all(rx));
		if (rx == x) {
			isp[i] = true;
			p[idx].push_back({b[i], i});
			continue;
		}
		rs[add(rx)].push_back({b[i], i});
	}

	int ans = 0;
	vector < bool > was(k, false);

	for (int i = 0; i < 1e6; i++) {
		sort(all(s[i]));
		sort(all(rs[i]));
		while (!s[i].empty() && !rs[i].empty()) {
			int si = s[i].back().second, rsi = rs[i].back().second;
			if (isp[si]) {
				s[i].pop_back();
				continue;
			}
			if (was[si]) {
				s[i].pop_back();
				continue;
			}
			if (was[rsi]) {
				rs[i].pop_back();
				continue;
			}
			if (b[si] + b[rsi] > 0) {
				was[si] = true;
				was[rsi] = true;
				ans += b[si] + b[rsi];
			}
			s[i].pop_back();
			rs[i].pop_back();
		}
	}

	vector < pair < int, int > > last;

	for (int i = 0; i < 1e6; i++) {
		sort(all(p[i]));
		for (int j = size(p[i]) - 1; j >= 0; j--) {
			int m1 = p[i][j].second;
			if (j > 0) {
				int m2 = p[i][j - 1].second;
				if (b[m1] + b[m2] > 0) {
					ans += b[m1] + b[m2];
					was[m1] = true;
					was[m2] = true;
					j--;
					continue;
				}
			}
			if (b[m1] > 0) {
				last.push_back({b[m1], m1});
			}
		}
	}

	sort(rall(last));

	for (auto v : last) {
		if (!was[v.second]) {
			ans += v.first;
			break;
		}
	}
	cout << ans;

	return 0;
}


#include <vector>
#include <algorithm>
#include <cmath>
#include <queue>
#include <string>
#include <set>
#include <climits>
#include <cstdio>
#include <iomanip>
#include <iterator>
#include <deque>
#include <map>
#include <cassert>
#include <ctime>

// #include <bits/stdc++.h>
#include <iostream>

using namespace std;

#define pb push_back
#define all(a) a.begin(), a.end()
#define rall(a) a.rbegin(), a.rend()
#define size(a) (int)a.size()
typedef long long ll;
typedef long double ld;
const int inf = 2e9;
const long double eps = 0.000001;
const long long mod = 1e9 + 7;
const long double PI = 3.14159265359;

template <class T>
struct MyVector : vector<T> {
	MyVector() : vector<T>() { }
	MyVector(int n) : vector<T>(n) { }
	T &operator [] (size_t i) {
		return vector<T>::at(i);
	}
};

struct Bohr {
	vector < int > nxt;
	bool leaf;
	Bohr() {
		nxt.resize(26, -1);
		leaf = false;
	}
};

vector < Bohr > t(1e6);
vector < vector < pair < int, int > > > s, rs;
vector < int > b;
vector < bool > isp;
int sz = 1;

int add(string s) {
	int it = 0;
	for (int i = 0; i < size(s); i++) {
		int a = s[i] - 'a';
		if (t[it].nxt[a] == -1) t[it].nxt[a] = sz, sz++;
		it = t[it].nxt[a];
	}

	t[it].leaf = true;
	return it;
}

int main() {
	ios_base::sync_with_stdio(false);
	cin.tie(nullptr);
	cout.tie(nullptr);
	#if _SLOVO
		freopen("input.txt", "r", stdin);
		freopen("output.txt", "w", stdout);
	#else
		//freopen(".in", "r", stdin);
		//freopen(".out", "w", stdout);
	#endif

	int k, n;
	cin >> k >> n;

	s.resize(1e6);
	rs.resize(1e6);
	b.resize(k);
	isp.resize(k, false);
	vector < vector < pair < int, int > > > p(1e6);

	for (int i = 0; i < k; i++) {
		string x;
		cin >> x;
		cin >> b[i];
		int idx;
		s[idx = add(x)].push_back({b[i], i});
		string rx = x;
		reverse(all(rx));
		if (rx == x) {
			isp[i] = true;
			p[idx].push_back({b[i], i});
			continue;
		}
		rs[add(rx)].push_back({b[i], i});
	}

	int ans = 0;
	vector < bool > was(k, false);

	for (int i = 0; i < 1e6; i++) {
		sort(all(s[i]));
		sort(all(rs[i]));
		while (!s[i].empty() && !rs[i].empty()) {
			int si = s[i].back().second, rsi = rs[i].back().second;
			if (isp[si]) {
				s[i].pop_back();
				continue;
			}
			if (was[si]) {
				s[i].pop_back();
				continue;
			}
			if (was[rsi]) {
				rs[i].pop_back();
				continue;
			}
			if (b[si] + b[rsi] > 0) {
				was[si] = true;
				was[rsi] = true;
				ans += b[si] + b[rsi];
			}
			s[i].pop_back();
			rs[i].pop_back();
		}
	}

	vector < pair < int, int > > last;

	for (int i = 0; i < 1e6; i++) {
		sort(all(p[i]));
		for (int j = size(p[i]) - 1; j >= 0; j--) {
			int m1 = p[i][j].second;
			if (j > 0) {
				int m2 = p[i][j - 1].second;
				if (b[m1] + b[m2] > 0) {
					ans += b[m1] + b[m2];
					was[m1] = true;
					was[m2] = true;
					j--;
					continue;
				}
			}
			if (b[m1] > 0) {
				last.push_back({b[m1], m1});
			}
		}
	}

	sort(rall(last));

	for (auto v : last) {
		if (!was[v.second]) {
			ans += v.first;
		}
	}
	cout << ans;

	return 0;
}


#include <bits/stdc++.h>
using namespace std;
//(≧∇≦) 私の名前はうずまきナルトと私は次の北城になります
//(≧∇≦) My name is Uzumaki Naruto and I will be the next Hokagi
const int OO = 0x3f3f3f3f ,N = 1e5+5 ,mod = 1e9+7 ;
const double pi = acos(-1) ,eps = 1e-9 ;
#define read(FILE)  freopen(FILE, "r", stdin);
#define write(FILE) freopen(FILE, "w", stdout);
#define Uzumaki_Naruto ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
typedef long long ll ;

int t ,n ,c ,indx ;
pair<int,string> arr[N] ;
string str ;
map<string,vector<int>> s ,rev_s ;
map<int,string> idx ;
map<string,bool> plind ,is ;
map<pair<pair<int,int>,bool>,ll> mem ;
map<pair<pair<int,int>,bool>,bool> vis ;
ll solve(int i,int j,bool take){
    if(i==indx)return 0;
    if(vis[{{i,j},take}])return mem[{{i,j},take}];
    vis[{{i,j},take}]=1;
    ll ret=solve(i+1,0,take);
    if(j<s[idx[i]].size()&&j<rev_s[idx[i]].size())ret=max(ret,solve(i,j+1,take)+s[idx[i]][j]+rev_s[idx[i]][j]);
    if(take==0&&j<s[idx[i]].size()&&plind[idx[i]])ret=max(ret,solve(i+1,j,1)+s[idx[i]][j]);
    return mem[{{i,j},take}]=ret;
}
int main(){
    Uzumaki_Naruto
    cin>>t>>n;
    for(int i=0;i<t;++i){
        cin>>str>>c ;
        arr[i]={c,str};
        bool flag=1;
        for(int i=0,j=n-1;i<j;++i,--j)if(str[i]!=str[j])flag=0;
        plind[str]=flag;
    }
    sort(arr,arr+t);
    reverse(arr,arr+t);
    for(int i=0;i<t;++i){
        str=arr[i].second;
        c=arr[i].first;
        string str2=str;
        reverse(str2.begin(),str2.end());
        if(str==str2){
            if(s[str2].size()>rev_s[str2].size())rev_s[str2].push_back(c);
            else s[str].push_back(c);
        }
        else{
            if(is[str2])rev_s[str2].push_back(c);
            else{
                is[str]=1;
                s[str].push_back(c);
            }
        }
        if(s[str].size()==0)s.erase(str);
        if(s[str2].size()==0)s.erase(str2);
        if(rev_s[str].size()==0)rev_s.erase(str);
        if(rev_s[str2].size()==0)rev_s.erase(str2);
    }
    for(auto&ptr:s)idx[indx++]=ptr.first;
    cout<<solve(0,0,0);
    return 0;
}


#include <bits/stdc++.h>
using namespace std;
//(≧∇≦) 私の名前はうずまきナルトと私は次の北城になります
//(≧∇≦) My name is Uzumaki Naruto and I will be the next Hokagi
const int OO = 0x3f3f3f3f ,N = 1e5+5 ,mod = 1e9+7 ;
const double pi = acos(-1) ,eps = 1e-9 ;
#define read(FILE)  freopen(FILE, "r", stdin);
#define write(FILE) freopen(FILE, "w", stdout);
#define Uzumaki_Naruto ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
typedef long long ll ;

int t ,n ,c ,indx ;
pair<int,string> arr[N] ;
string str ;
map<string,vector<int>> s ,rev_s ;
map<int,string> idx ;
map<string,bool> plind ,is ;
map<pair<pair<int,int>,bool>,ll> mem ;
map<pair<pair<int,int>,bool>,bool> vis ;
ll solve(int i,int j,bool take){
    if(i==indx)return 0;
    if(vis[{{i,j},take}])return mem[{{i,j},take}];
    vis[{{i,j},take}]=1;
    ll ret=solve(i+1,0,take);
    if(j<s[idx[i]].size()&&j<rev_s[idx[i]].size())ret=max(ret,solve(i,j+1,take)+s[idx[i]][j]+rev_s[idx[i]][j]);
    if(take==0&&j<s[idx[i]].size()&&plind[idx[i]])ret=max(ret,solve(i+1,0,1)+s[idx[i]][j]);
    return mem[{{i,j},take}]=ret;
}
int main(){
    Uzumaki_Naruto
    cin>>t>>n;
    for(int i=0;i<t;++i){
        cin>>str>>c ;
        arr[i]={c,str};
        bool flag=1;
        for(int i=0,j=n-1;i<j;++i,--j)if(str[i]!=str[j])flag=0;
        plind[str]=flag;
    }
    sort(arr,arr+t);
    reverse(arr,arr+t);
    for(int i=0;i<t;++i){
        str=arr[i].second;
        c=arr[i].first;
        string str2=str;
        reverse(str2.begin(),str2.end());
        if(str==str2){
            if(s[str2].size()>rev_s[str2].size())rev_s[str2].push_back(c);
            else s[str].push_back(c);
        }
        else{
            if(is[str2])rev_s[str2].push_back(c);
            else{
                is[str]=1;
                s[str].push_back(c);
            }
        }
        if(s[str].size()==0)s.erase(str);
        if(s[str2].size()==0)s.erase(str2);
        if(rev_s[str].size()==0)rev_s.erase(str);
        if(rev_s[str2].size()==0)rev_s.erase(str2);
    }
    for(auto&ptr:s)idx[indx++]=ptr.first;
    cout<<solve(0,0,0);
    return 0;
}


#include <bits/stdc++.h>
using namespace std;
//(≧∇≦) 私の名前はうずまきナルトと私は次の北城になります
//(≧∇≦) My name is Uzumaki Naruto and I will be the next Hokagi
const int OO = 0x3f3f3f3f ,N = 1e5+5 ,mod = 1e9+7 ;
const double pi = acos(-1) ,eps = 1e-9 ;
#define read(FILE)  freopen(FILE, "r", stdin);
#define write(FILE) freopen(FILE, "w", stdout);
#define Uzumaki_Naruto ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
typedef long long ll ;

int t ,n ,c ,indx ;
pair<int,string> arr[N] ;
string str ;
map<string,vector<int>> s ,rev_s ;
map<int,string> idx ;
map<string,bool> plind ;
map<pair<pair<int,int>,bool>,ll> mem ;
map<pair<pair<int,int>,bool>,bool> vis ;
ll solve(int i,int j,bool take){
    if(i==indx)return 0;
    if(vis[{{i,j},take}])return mem[{{i,j},take}];
    vis[{{i,j},take}]=1;
    ll ret=solve(i+1,0,take);
    if(j<s[idx[i]].size()&&j<rev_s[idx[i]].size())ret=max(ret,solve(i,j+1,take)+s[idx[i]][j]+rev_s[idx[i]][j]);
    if(take==0&&plind[idx[i]])ret=max(ret,solve(i+1,j,1)+s[idx[i]][j]);
    return mem[{{i,j},take}]=ret;
}
int main(){
    cin>>t>>n;
    for(int i=0;i<t;++i){
        cin>>str>>c ;
        arr[i]={c,str};
        bool flag=1;
        for(int i=0,j=n-1;i<j;++i,--j)if(str[i]!=str[j])flag=0;
        plind[str]=flag;
    }
    sort(arr,arr+t);
    reverse(arr,arr+t);
    for(int i=0;i<t;++i){
        str=arr[i].second;
        c=arr[i].first;
        string str2=str;
        reverse(str2.begin(),str2.end());
        if(s[str2].size()>rev_s[str2].size())rev_s[str2].push_back(c);
        else s[str].push_back(c);
        if(s[str].size()==0)s.erase(str);
        if(s[str2].size()==0)s.erase(str2);
        if(rev_s[str].size()==0)rev_s.erase(str);
        if(rev_s[str2].size()==0)rev_s.erase(str2);
    }
    for(auto&ptr:s)idx[indx++]=ptr.first;
    cout<<solve(0,0,0);
    return 0;
}


#include<bits/stdc++.h>
#define mp make_pair
#define i1 first
#define i2 second
using namespace std;
int N, K, B, H=0, Hc=0, P=0, Pc=0, s1, s2, nop, negmax, posmin, mins, v, i, j;
string S, R;
map <string,int> M, Mc;
vector < pair < vector <int>,vector <int> > > V;
vector < vector <int> > Vc;
vector <int> emp;
string rev(string S) {
	int i=K;
	string R="";
	while (i) {
		i--;
		R+=S[i];
	}
	return R;
}
int main () {
	ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0);
	cin>>N>>K;
	for (i=0;i<N;i++) {
		cin>>S>>B;
		R=rev(S);
		if (S==R) {
			v=Mc[S];
			if (v==0) {
				Vc.push_back(emp);
				Vc[Pc].push_back(B);
				Pc++;
				Mc[S]=Pc;
			}
			else Vc[v-1].push_back(B);
		}
		else {
			v=M[S];
			if (v==0) {
				V.push_back(mp(emp,emp));
				if (S<R) {
					V[P].i1.push_back(B);
					P++;
					M[S]=P;
					M[R]=-P;
				}
				else {
					V[P].i2.push_back(B);
					P++;
					M[S]=-P;
					M[R]=P;
				}
			}
			else {
				if (v>0) {
					V[v-1].i1.push_back(B);
				}
				else V[-v-1].i2.push_back(B);
			}
		}
	}
	for (i=0;i<P;i++) {
		s1=V[i].i1.size();
		s2=V[i].i2.size();
		mins=min(s1,s2);
		if (mins) {
			sort(V[i].i1.begin(),V[i].i1.end());
			sort(V[i].i2.begin(),V[i].i2.end());
			for (j=1;j<=mins;j++) {
				v=V[i].i1[s1-j]+V[i].i2[s2-j];
				if (v>0) {
					H+=v;
				}
				else break;
			}
		}
	}
	for (i=0;i<Pc;i++) {
		s1=Vc[i].size();
		nop=0;
		negmax=-10001;
		posmin=10001;
		for (j=0;j<s1;j++) {
			if (Vc[i][j]>0) {
				nop++;
				H+=Vc[i][j];
				posmin=min(posmin,Vc[i][j]);
			}
			else negmax=max(negmax,Vc[i][j]);
		}
		if (nop%2) {
			if (negmax==-10001) {
				H-=posmin;
				Hc=max(Hc,posmin);
			}
			else if (-negmax<posmin) {
				H+=negmax;
				Hc=max(Hc,-negmax);
			}
			else {
				H-=posmin;
				Hc=max(Hc,posmin);
			}
		}
	}
	cout<<H+Hc<<endl;
}


#include<bits/stdc++.h>
#define mp make_pair
#define i1 first
#define i2 second
using namespace std;
int N, K, B, H=0, Hc=0, P=0, Pc=0, s1, s2, mins, maks, v, i, j;
string S, R;
map <string,int> M, Mc;
vector < pair < vector <int>,vector <int> > > V;
vector < vector <int> > Vc;
vector <int> emp;
string rev(string S) {
	int i=K;
	string R="";
	while (i) {
		i--;
		R+=S[i];
	}
	return R;
}
int main () {
	ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0);
	cin>>N>>K;
	for (i=0;i<N;i++) {
		cin>>S>>B;
		R=rev(S);
		if (S==R) {
			v=Mc[S];
			if (v==0) {
				Vc.push_back(emp);
				Vc[Pc].push_back(B);
				Pc++;
				Mc[S]=Pc;
			}
			else Vc[v-1].push_back(B);
		}
		else {
			v=M[S];
			if (v==0) {
				V.push_back(mp(emp,emp));
				if (S<R) {
					V[P].i1.push_back(B);
					P++;
					M[S]=P;
					M[R]=-P;
				}
				else {
					V[P].i2.push_back(B);
					P++;
					M[S]=-P;
					M[R]=P;
				}
			}
			else {
				if (v>0) {
					V[v-1].i1.push_back(B);
				}
				else V[-v-1].i2.push_back(B);
			}
		}
	}
	for (i=0;i<P;i++) {
		s1=V[i].i1.size();
		s2=V[i].i2.size();
		mins=min(s1,s2);
		if (mins) {
			sort(V[i].i1.begin(),V[i].i1.end());
			sort(V[i].i2.begin(),V[i].i2.end());
			for (j=1;j<=mins;j++) {
				v=V[i].i1[s1-j]+V[i].i2[s2-j];
				if (v>0) {
					H+=v;
				}
				else break;
			}
		}
	}
	for (i=0;i<Pc;i++) {
		s1=Vc[i].size();
		maks=10000;
		for (j=0;j<s1;j++) {
			H+=Vc[i][j];
			maks=min(maks,Vc[i][j]);
		}
		if (s1%2) {
			H-=maks;
			Hc=max(Hc,maks);
		}
	}
	cout<<H+Hc<<endl;
}


#include<bits/stdc++.h>
#define mp make_pair
#define i1 first
#define i2 second
using namespace std;
int N, K, B, H=0, Hc=0, P=0, Pc=0, s1, s2, mins, maks, v, i, j;
string S, R;
map <string,int> M, Mc;
vector < pair < vector <int>,vector <int> > > V;
vector < vector <int> > Vc;
vector <int> emp;
string rev(string S) {
	int i=K;
	string R="";
	while (i) {
		i--;
		R+=S[i];
	}
	return R;
}
int main () {
	ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0);
	cin>>N>>K;
	for (i=0;i<N;i++) {
		cin>>S>>B;
		R=rev(S);
		if (S==R) {
			//cout<<"=="<<endl;
			v=Mc[S];
			if (v==0) {
				Vc.push_back(emp);
				Vc[Pc].push_back(B);
				Pc++;
				Mc[S]=Pc;
			}
			else Vc[v-1].push_back(B);
		}
		else {
			v=M[S];
			if (v==0) {
				V.push_back(mp(emp,emp));
				if (S<R) {
					V[P].i1.push_back(B);
					P++;
					M[S]=P;
					M[R]=-P;
				}
				else {
					V[P].i2.push_back(B);
					P++;
					M[S]=-P;
					M[R]=P;
				}
			}
			else {
				if (v>0) {
					V[v-1].i1.push_back(B);
				}
				else V[-v-1].i2.push_back(B);
			}
		}
	}
	/*for (i=0;i<Pc;i++) {
		for (j=0;j<Vc[i].size();j++) {
			cout<<Vc[i][j]<<" ";
		}
		cout<<endl;
	}
	for (i=0;i<P;i++) {
		for (j=0;j<V[i].i1.size();j++) {
			cout<<V[i].i1[j]<<" ";
		}
		cout<<endl;
		for (j=0;j<V[i].i2.size();j++) {
			cout<<V[i].i2[j]<<" ";
		}
		cout<<endl;
	}*/
	for (i=0;i<P;i++) {
		s1=V[i].i1.size();
		s2=V[i].i2.size();
		mins=min(s1,s2);
		if (mins) {
			sort(V[i].i1.begin(),V[i].i1.end());
			sort(V[i].i2.begin(),V[i].i2.end());
			for (j=1;j<=mins;j++) {
				v=V[i].i1[s1-j]+V[i].i2[s2-j];
				if (v>0) {
					H+=v;
				}
				else break;
			}
		}
	}
	for (i=0;i<Pc;i++) {
		s1=Vc[i].size();
		maks=-10000;
		for (j=0;j<s1;j++) {
			H+=Vc[i][j];
			maks=max(maks,Vc[i][j]);
		}
		if (s1%2) {
			H-=maks;
			Hc=max(Hc,maks);
		}
	}
	cout<<H+Hc<<endl;
}


#include <bits/stdc++.h>
#define MAXN 100005
#define INF 1000000000
using namespace std;

struct si {
	string a;
	int b, c;

	bool operator < (si o) const {
		return tie(a, b, c) < tie(o.a, o.b, o.c);
	}
};

int N, K, x, y, ans;
string rev[MAXN];
si arr[MAXN];

string balik(string s) {
	string ret;
	for (int i = s.length()-1; i >= 0; i--) {
		ret += s[i];
	}
	return ret;
}

int main() {
	ios::sync_with_stdio(0); cin.tie(0);

	cin >> N >> K;
	for (int i = 0; i < N; i++) {
		string x;
		cin >> x >> y;
		arr[i] = {x, 0, y};
	}
	sort(arr, arr+N);
	for (int i = 0; i < N; i++) {
		//~ cout << arr[i].a << '\n';
		rev[i] = balik(arr[i].a);
	}

	int mid = 0;
	ans = 0;
	for (int i = N-1; i >= 0; i--) {
		if (arr[i].b) continue;
		int pos = upper_bound(arr, arr+i, (si){rev[i], 0, INF}) - arr - 1;
		if (arr[pos].a != rev[i]) {
			if (arr[i].a == rev[i]) mid = max(mid, arr[i].c);
			else continue;
		}
		else {
			if (arr[i].c + arr[pos].c > 0) {
				ans += arr[i].c + arr[pos].c;
				arr[i].b = arr[pos].b = 1;
				if (arr[i].a == rev[i]) {
					mid = max(mid, -arr[pos].c);
				}
			}
			else if (arr[i].a == rev[i]) {
				mid = max(mid, arr[i].c);
			}
		}
	}
	ans += mid;
	cout << ans << '\n';

	return 0;
}


#include <bits/stdc++.h>
#define MAXN 100005
#define INF 1000000000
using namespace std;

struct si {
	string a;
	int b, c;

	bool operator < (si o) const {
		return tie(a, b, c) < tie(o.a, o.b, o.c);
	}
};

int N, K, x, y, ans;
string rev[MAXN];
si arr[MAXN];

string balik(string s) {
	string ret;
	for (int i = s.length()-1; i >= 0; i--) {
		ret += s[i];
	}
	return ret;
}

int main() {
	ios::sync_with_stdio(0); cin.tie(0);

	cin >> N >> K;
	for (int i = 0; i < N; i++) {
		string x;
		cin >> x >> y;
		arr[i] = {x, 0, y};
	}
	sort(arr, arr+N);
	for (int i = 0; i < N; i++) {
		//~ cout << arr[i].a << '\n';
		rev[i] = balik(arr[i].a);
	}

	int mid = 0;
	ans = 0;
	for (int i = N-1; i >= 0; i--) {
		if (arr[i].b) continue;
		int pos = upper_bound(arr, arr+i, (si){rev[i], 0, INF}) - arr - 1;
		if (arr[pos].a != rev[i]) {
			if (arr[i].a == rev[i]) mid = max(mid, arr[i].c);
			else continue;
		}
		else {
			if (arr[i].a == rev[i] && arr[pos].c < 0) {
				ans += arr[i].c;
			}
			else if (arr[i].c + arr[pos].c > 0) {
				ans += arr[i].c + arr[pos].c;
				arr[i].b = arr[pos].b = 1;
			}
		}
	}
	ans += mid;
	cout << ans << '\n';

	return 0;
}


#include <bits/stdc++.h>
#define MAXN 100005
#define INF 1000000000
using namespace std;

struct si {
	string a;
	int b, c;

	bool operator < (si o) const {
		return tie(a, b, c) < tie(o.a, o.b, o.c);
	}
};

int N, K, x, y, ans;
string rev[MAXN];
si arr[MAXN];

string balik(string s) {
	string ret;
	for (int i = s.length()-1; i >= 0; i--) {
		ret += s[i];
	}
	return ret;
}

int main() {
	ios::sync_with_stdio(0); cin.tie(0);

	cin >> N >> K;
	for (int i = 0; i < N; i++) {
		string x;
		cin >> x >> y;
		arr[i] = {x, 0, y};
	}
	sort(arr, arr+N);
	for (int i = 0; i < N; i++) {
		//~ cout << arr[i].a << '\n';
		rev[i] = balik(arr[i].a);
	}

	int mid = 0;
	ans = 0;
	for (int i = N-1; i >= 0; i--) {
		if (arr[i].b) continue;
		int pos = upper_bound(arr, arr+i, (si){rev[i], 0, INF}) - arr - 1;
		if (arr[pos].a != rev[i]) {
			if (arr[i].a == rev[i]) mid = max(mid, arr[i].c);
			else continue;
		}
		else {
			if (arr[i].c + arr[pos].c > 0) {
				ans += arr[i].c + arr[pos].c;
				arr[i].b = arr[pos].b = 1;
			}
		}
	}
	ans += mid;
	cout << ans << '\n';

	return 0;
}


#include <bits/stdc++.h>

using namespace std;

#define ss second
#define ff first
#define p_b push_back

string rvs (string s) {
    for (int i = 0; i < s.size() / 2; i++) {
        swap (s[i], s[s.size() - 1 - i]);
    }
    return s;
}

int main () {
    // ios_base::sync_with_stdio(0);
#ifdef LOCAL
    freopen ("input.txt", "r", stdin);
    freopen ("output.txt", "w", stdout);
#endif // LOCAL
    int n, rofl;
    cin >> n >> rofl;
    vector < pair < int, string > > v;
    for (int i = 0; i < n; i++) {
        int x;
        string s;
        cin >> s >> x;
        v.p_b({x, s});
    }
    sort (v.begin(), v.end());
    map < string, vector < int > > m;
    vector < pair < int, int > > nom;
    long long ans = 0;
    for (int i = 0; i < v.size(); i++) {
        m[v[i].ss].p_b(v[i].ff);
    }
    //cerr << "39" << endl;
    vector < string > pal;
    for (int i = 0; i < n; i++) {
        //cerr << i << endl;
        string s = v[i].ss;
        string r = rvs(s);
        if (s == r) {
            pal.p_b(s);
            while (m[s].size() > 1) {
                int kek = m[s][m[s].size() - 1] + m[s][m[s].size() - 2];
                if (m[s][m[s].size() - 1] > 0 && m[s][m[s].size() - 2] < 0) {
                    nom.p_b({m[s][m[s].size() - 1], max (0, kek)});
                }
                if (kek > 0) {
                    ans += kek;
                    m[s].erase(m[s].end() - 2, m[s].end());
                } else break;
            }
        } else {
            while (m[s].size() && m[r].size()) {
                int kek = m[s][m[s].size() - 1] + m[r][m[r].size() - 1];
                if (kek > 0) {
                    ans += kek;
                    m[s].erase(m[s].end() - 1);
                    m[r].erase(m[r].end() - 1);
                }
                else break;
            }
        }
    }
    //cerr << "67" << endl;
    //cout << ans << endl;
    int kek = 0;
    for (auto i : nom) kek = max (kek, i.ff - i.ss);
    for (int i = 0; i < pal.size(); i++) {
        string s = pal[i];
        if (m[s].size()) {
            kek = max (kek, m[s][m[s].size() - 1]);
        }
    }
    ans += kek;
    cout << ans << endl;
}


#include <iostream>
#include <vector>
#include <queue>
#include <functional>
#include <algorithm>
#define MAX 10001
using namespace std;

vector <int> col[MAX];
vector <int> row[MAX];

vector <int> d_row[MAX];
vector <int> d_col[MAX];

struct spot {
	int r;
	int c;
	int distance;

	bool operator<(const spot& rhs) const {
		return distance > rhs.distance;
	}
};

priority_queue <spot> q;

int n, m, k;

int main() {
	int r, c;
	spot temp;

	cin >> n >> m >> k;
	for (int i = 0; i < k; ++i) {
		cin >> r >> c;
		row[r].push_back(c);
		col[c].push_back(r);
		d_row[r].push_back(MAX * 10);
		d_col[c].push_back(MAX * 10);
	}
	//row[n].push_back(m);
	//col[m].push_back(n);
	//d_row[n].push_back(MAX * 10);
	//d_col[m].push_back(MAX * 10);

	temp.r = 1;
	temp.c = 1;
	temp.distance = 0;
	q.push(temp);
	while (!q.empty()) {
		spot top = q.top();
		q.pop();
		//cout << top.r << " " << top.c << " " << top.distance << endl;
		// row 탐색
		for (r = max(top.r - 2, 1); r <= min(n, top.r + 2); ++r) {
			if (r > 0 && r <= n) {
				// row 고정
				for (int j = 0; j < row[r].size(); ++j) {
					c = row[r][j];
					if (abs(top.r - r) + abs(top.c - c) <= 1 && top.distance < d_row[r][j]) {
						d_row[r][j] = top.distance;
						temp.r = r;
						temp.c = c;
						temp.distance = top.distance;
						q.push(temp);
					}

					else if (top.distance + 1 < d_row[r][j]) {
						d_row[r][j] = top.distance + 1;
						temp.r = r;
						temp.c = c;
						temp.distance = top.distance + 1;
						q.push(temp);
					}
				}
			}
		}

		// col 탐색
		for (c = max(top.c - 2, 1); c <= min(top.c + 2, m); ++c) {
			if (c > 0 && c <= m) {
				// col 고정
				for (int j = 0; j < col[c].size(); ++j) {
					r = col[c][j];
					if (abs(top.r - r) + abs(top.c - c) <= 1 && top.distance < d_col[c][j]) {
						d_col[c][j] = top.distance;
						temp.r = r;
						temp.c = c;
						temp.distance = top.distance;
						q.push(temp);
					}

					else if (top.distance + 1 < d_col[c][j]) {
						d_col[c][j] = top.distance + 1;
						temp.r = r;
						temp.c = c;
						temp.distance = top.distance + 1;
						q.push(temp);
					}
				}
			}
		}
	}

	int Min = MAX * 10;
	for (r = n - 1; r <= n; ++r) {
		for (int j = 0; j < d_row[r].size(); ++j) Min = min(Min, d_row[r][j] + 1);
	}

	for (c = m - 1; c <= m; ++c) {
		for (int j = 0; j < d_col[c].size(); ++j) Min = min(Min, d_col[c][j] + 1);
	}

	if (row[n].size() > 0 && row[n][row[n].size() - 1] == m) Min = min(Min, d_row[n][d_row[n].size() - 1]);
	if (col[m].size() > 0 && col[m][col[m].size() - 1] == n) Min = min(Min, d_col[m][d_col[m].size() - 1]);

	if (Min == MAX * 10) cout << -1 << endl;
	else cout << Min << endl;

	//while (1);

}


#include <iostream>
#include <vector>
#include <queue>
#include <functional>
#include <algorithm>
#define MAX 10001
using namespace std;

vector <int> col[MAX];
vector <int> row[MAX];

vector <int> d_row[MAX];
vector <int> d_col[MAX];

struct spot {
	int r;
	int c;
	int distance;

	bool operator<(const spot& rhs) const {
		return distance > rhs.distance;
	}
};

priority_queue <spot> q;

int n, m, k;

int main() {
	int r, c;
	spot temp;

	cin >> n >> m >> k;
	for (int i = 0; i < k; ++i) {
		cin >> r >> c;
		row[r].push_back(c);
		col[c].push_back(r);
		d_row[r].push_back(MAX * 10);
		d_col[c].push_back(MAX * 10);
	}
	//row[n].push_back(m);
	//col[m].push_back(n);
	//d_row[n].push_back(MAX * 10);
	//d_col[m].push_back(MAX * 10);

	temp.r = 1;
	temp.c = 1;
	temp.distance = 0;
	q.push(temp);
	while (!q.empty()) {
		spot top = q.top();
		q.pop();
		//cout << top.r << " " << top.c << " " << top.distance << endl;
		// row 탐색
		for (r = max(top.r - 2, 1); r <= min(n, top.r + 2); ++r) {
			if (r > 0 && r <= n) {
				// row 고정
				for (int j = 0; j < row[r].size(); ++j) {
					c = row[r][j];
					if (abs(top.r - r) + abs(top.c - c) <= 1 && top.distance < d_row[r][j]) {
						d_row[r][j] = top.distance;
						temp.r = r;
						temp.c = c;
						temp.distance = top.distance;
						q.push(temp);
					}

					else if (top.distance + 1 < d_row[r][j]) {
						d_row[r][j] = top.distance + 1;
						temp.r = r;
						temp.c = c;
						temp.distance = top.distance + 1;
						q.push(temp);
					}
				}
			}
		}

		// col 탐색
		for (c = max(top.c - 2, 1); c <= min(top.c + 2, m); ++c) {
			if (c > 0 && c <= m) {
				// col 고정
				for (int j = 0; j < col[c].size(); ++j) {
					r = col[c][j];
					if (abs(top.r - r) + abs(top.c - c) <= 1 && top.distance < d_col[c][j]) {
						d_col[c][j] = top.distance;
						temp.r = r;
						temp.c = c;
						temp.distance = top.distance;
						q.push(temp);
					}

					else if (top.distance + 1 < d_col[c][j]) {
						d_col[c][j] = top.distance + 1;
						temp.r = r;
						temp.c = c;
						temp.distance = top.distance + 1;
						q.push(temp);
					}
				}
			}
		}
	}

	int Min = MAX * 10;
	for (r = n - 1; r <= n; ++r) {
		for (int j = 0; j < d_row[r].size(); ++j) {
			if (r == n && row[r][j] == c) Min = min(Min, d_row[r][j]);
			else Min = min(Min, d_row[r][j] + 1);
		}
	}

	for (c = m - 1; c <= m; ++c) {
		for (int j = 0; j < d_col[c].size(); ++j) {
			if (c == m && col[c][j] == r) Min = min(Min, d_col[c][j]);
			else Min = min(Min, d_col[c][j] + 1);
		}
	}

	if (Min == MAX * 10) cout << -1 << endl;
	else cout << Min << endl;
}


#include <iostream>
#include <vector>
#include <queue>
#include <functional>
#include <algorithm>
#define MAX 10001
using namespace std;

vector <int> col[MAX];
vector <int> row[MAX];

vector <int> d_row[MAX];
vector <int> d_col[MAX];

struct spot {
	int r;
	int c;
	int distance;

	bool operator<(const spot& rhs) const {
		return distance > rhs.distance;
	}
};

priority_queue <spot> q;

int n, m, k;

int main() {
	int r, c;

	cin >> n >> m >> k;
	for (int i = 0; i < k; ++i) {
		cin >> r >> c;
		row[r].push_back(c);
		col[c].push_back(r);
		d_row[r].push_back(MAX * 10);
		d_col[c].push_back(MAX * 10);
	}
	//row[n].push_back(m);
	//col[m].push_back(n);
	//d_row[n].push_back(MAX * 10);
	//d_col[m].push_back(MAX * 10);

	q.push(spot{ 1,1,0 });
	while (!q.empty()) {
		spot top = q.top();
		q.pop();
		//cout << top.r << " " << top.c << " " << top.distance << endl;
		// row 탐색
		for (r = max(top.r - 2, 1); r <= min(n, top.r + 2); ++r) {
			if (r > 0 && r <= n) {
				// row 고정
				for (int j = 0; j < row[r].size(); ++j) {
					c = row[r][j];
					if (abs(top.r - r) + abs(top.c - c) <= 1 && top.distance < d_row[r][j]) {
						d_row[r][j] = top.distance;
						q.push(spot{ r, c, top.distance });
					}

					else if (top.distance + 1 < d_row[r][j]) {
						d_row[r][j] = top.distance + 1;
						q.push(spot{ r, c, top.distance + 1 });
					}
				}
			}
		}

		// col 탐색
		for (c = max(top.c - 2, 1); c <= min(top.c + 2, m); ++c) {
			if (c > 0 && c <= m) {
				// col 고정
				for (int j = 0; j < col[c].size(); ++j) {
					r = col[c][j];
					if (abs(top.r - r) + abs(top.c - c) <= 1 && top.distance < d_col[c][j]) {
						d_col[c][j] = top.distance;
						q.push(spot{ r, c, top.distance });
					}

					else if (top.distance + 1 < d_col[c][j]) {
						d_col[c][j] = top.distance + 1;
						q.push(spot{ r, c, top.distance + 1});
					}
				}
			}
		}
	}

	int Min = MAX * 10;
	for (r = n - 1; r <= n; ++r) {
		for (int j = 0; j < d_row[r].size(); ++j) Min = min(Min, d_row[r][j] + 1);
	}

	for (c = m - 1; c <= m; ++c) {
		for (int j = 0; j < d_col[c].size(); ++j) Min = min(Min, d_col[c][j] + 1);
	}

	if (row[n].size() > 0 && row[n][row[n].size() - 1] == m) Min = min(Min, d_row[n][d_row[n].size() - 1]);
	if (col[m].size() > 0 && col[m][col[m].size() - 1] == n) Min = min(Min, d_col[m][d_col[m].size() - 1]);

	if (Min == MAX * 10) cout << -1 << endl;
	else cout << Min << endl;

	//while (1);

}


#define _USE_MATH_DEFINES
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <vector>
#include <algorithm>
#include <stack>
#include <map>
#include <functional>
#include <cstring>
#include <queue>
#include <cmath>
#include <deque>
#include <list>
#include <iomanip>
#include <fstream>
#include <string>
#include <iterator>
#include <set>
#include <bitset>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair <int, int> pii;
#define mp make_pair
#define pb push_back
#define FOR(i, a, b) for (int i = (a); i < (b); ++i)
#define REP(i, N) FOR(i, 0, N)
#define SZ(x) ((int)(x).size())

const int MAXK = 10007, INF = 1000000007;

int main()
{
	int n, m, k, cc[MAXK], r[MAXK], c[MAXK], cur = 0, v, d[MAXK], s, f = -1, ans = INF;
	queue <int> Q;
	pair <pii, pii> b[MAXK];
	bool used[MAXK], inth, intv;
	scanf("%d%d%d", &n, &m, &k);
	REP(i, k){
		scanf("%d%d", r + i, c + i);
		b[i].first = b[i].second = mp(INF, -1);
		d[i] = INF;
		if (r[i] == 1 && c[i] == 1) s = i;
		if (r[i] == n && c[i] == m) f = i;
	}
	memset(used, 0, MAXK);
	REP(i, k){
		if (!used[i]){
			Q.push(i); used[i] = true;
			while(!Q.empty()){
				v = Q.front();
				Q.pop();
				cc[v] = cur;
				b[cur].first.first = min(b[cur].first.first, c[v]);
				b[cur].first.second = max(b[cur].first.second, c[v]);
				b[cur].second.first = min(b[cur].second.first, r[v]);
				b[cur].second.second = max(b[cur].second.second, r[v]);
				REP(j, k)
					if (!used[j] && (abs(r[j] - r[v]) + abs(c[j] - c[v]) == 1)){
						Q.push(j);
						used[j] = true;
					}
			}
			++cur;
		}
	}
	memset(used, 0, MAXK);
	d[cc[s]] = 0;
	used[cc[s]] = true;
	Q.push(cc[s]);
	while (!Q.empty()){
		v = Q.front();
		Q.pop();
		REP(j, cur){
			if (!used[j]){
				inth = ((b[j].first.first <= b[v].first.second + 2) && (b[v].first.first <= b[j].first.second + 2));
				intv = ((b[j].second.first <= b[v].second.second + 2) && (b[v].second.first <= b[j].second.second + 2));
				if (inth || intv) {Q.push(j); used[j] = true; d[j] = d[v] + 1;}
			}
		}
	}
	if (f != -1) ans = d[cc[f]];
	REP(i, cur){
		if ((b[i].first.second >= m - 1) || (b[i].second.second >= n - 1))
			ans = min(ans, d[i] + 1);
	}
	if (ans >= INF) ans = -1;
	printf("%d", ans);
	//cout << endl; system("pause");
	return 0;
}//don't forget about const
/*

*/


#define _USE_MATH_DEFINES
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <vector>
#include <algorithm>
#include <stack>
#include <map>
#include <functional>
#include <cstring>
#include <queue>
#include <cmath>
#include <deque>
#include <list>
#include <iomanip>
#include <fstream>
#include <string>
#include <iterator>
#include <set>
#include <bitset>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair <int, int> pii;
#define mp make_pair
#define pb push_back
#define FOR(i, a, b) for (int i = (a); i < (b); ++i)
#define REP(i, N) FOR(i, 0, N)
#define SZ(x) ((int)(x).size())

const int MAXN = 107, MAXK = 10007, INF = 1000000007;

int main()
{
	int n, m, k, cc[MAXK], r[MAXK], c[MAXK], cur = 0, v, d[MAXK], s, f = -1, ans = INF;
	queue <int> Q;
	pair <pii, pii> b[MAXK];
	bool used[MAXK], inth, intv;
	scanf("%d%d%d", &n, &m, &k);
	REP(i, k){
		scanf("%d%d", r + i, c + i);
		b[i].first = b[i].second = mp(INF, -1);
		d[i] = INF;
		if (r[i] == 1 && c[i] == 1) s = i;
		if (r[i] == n && c[i] == n) f = i;
	}
	memset(used, 0, MAXK);
	REP(i, k){
		if (!used[i]){
			Q.push(i); used[i] = true;
			while(!Q.empty()){
				v = Q.front();
				Q.pop();
				cc[v] = cur;
				b[cur].first.first = min(b[cur].first.first, c[v]);
				b[cur].first.second = max(b[cur].first.second, c[v]);
				b[cur].second.first = min(b[cur].second.first, r[v]);
				b[cur].second.second = max(b[cur].second.second, r[v]);
				REP(j, k)
					if (!used[j] && abs(r[j] - r[v]) + abs(c[j] - c[v]) == 1){
						Q.push(j);
						used[j] = true;
					}
			}
			++cur;
		}
	}
	memset(used, 0, MAXK);
	d[cc[s]] = 0;
	used[cc[s]] = true;
	Q.push(cc[s]);
	while (!Q.empty()){
		v = Q.front();
		Q.pop();
		REP(j, cur){
			if (!used[j]){
				inth = (b[j].first.first <= b[v].first.second + 2 && b[v].first.first <= b[j].first.second + 2);
				intv = (b[j].second.first <= b[v].second.second + 2 && b[v].second.first <= b[j].second.second + 2);
				if (inth || intv) {Q.push(j); used[j] = true; d[j] = d[v] + 1;}
			}
		}
	}
	if (f != -1) {printf("%d", d[cc[f]]); return 0;}
	REP(i, cur){
		if (b[i].first.second >= n - 1 || b[i].second.second >= m - 1)
			ans = min(ans, d[i] + 1);
	}
	if (ans >= INF) ans = -1;
	printf("%d", ans);
	//cout << endl; system("pause");
	return 0;
}//don't forget about const
/*

*/


#define _USE_MATH_DEFINES
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <vector>
#include <algorithm>
#include <stack>
#include <map>
#include <functional>
#include <cstring>
#include <queue>
#include <cmath>
#include <deque>
#include <list>
#include <iomanip>
#include <fstream>
#include <string>
#include <iterator>
#include <set>
#include <bitset>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair <int, int> pii;
#define mp make_pair
#define pb push_back
#define FOR(i, a, b) for (int i = (a); i < (b); ++i)
#define REP(i, N) FOR(i, 0, N)
#define SZ(x) ((int)(x).size())

const int MAXK = 10007, INF = 1000000007;

int main()
{
	int n, m, k, cc[MAXK], r[MAXK], c[MAXK], cur = 0, v, d[MAXK], s, f = -1, ans = INF;
	queue <int> Q;
	pair <pii, pii> b[MAXK];
	bool used[MAXK], inth, intv;
	scanf("%d%d%d", &n, &m, &k);
	REP(i, k){
		scanf("%d%d", r + i, c + i);
		b[i].first = b[i].second = mp(INF, -1);
		d[i] = INF;
		if (r[i] == 1 && c[i] == 1) s = i;
		if (r[i] == n && c[i] == m) f = i;
	}
	memset(used, 0, MAXK);
	REP(i, k){
		if (!used[i]){
			Q.push(i); used[i] = true;
			while(!Q.empty()){
				v = Q.front();
				Q.pop();
				cc[v] = cur;
				b[cur].first.first = min(b[cur].first.first, c[v]);
				b[cur].first.second = max(b[cur].first.second, c[v]);
				b[cur].second.first = min(b[cur].second.first, r[v]);
				b[cur].second.second = max(b[cur].second.second, r[v]);
				REP(j, k)
					if (!used[j] && (abs(r[j] - r[v]) + abs(c[j] - c[v]) == 1)){
						Q.push(j);
						used[j] = true;
					}
			}
			++cur;
		}
	}
	memset(used, 0, MAXK);
	d[cc[s]] = 0;
	used[cc[s]] = true;
	Q.push(cc[s]);
	while (!Q.empty()){
		v = Q.front();
		Q.pop();
		REP(j, cur){
			if (!used[j]){
				inth = ((b[j].first.first <= b[v].first.second + 2) && (b[v].first.first <= b[j].first.second + 2));
				intv = ((b[j].second.first <= b[v].second.second + 2) && (b[v].second.first <= b[j].second.second + 2));
				if (inth || intv) {Q.push(j); used[j] = true; d[j] = d[v] + 1;}
			}
		}
	}
	if (f != -1) ans = d[cc[f]];
	REP(i, cur){
		if ((b[i].first.second >= n - 1) || (b[i].second.second >= m - 1))
			ans = min(ans, d[i] + 1);
	}
	if (ans >= INF) ans = -1;
	printf("%d", ans);
	//cout << endl; system("pause");
	return 0;
}//don't forget about const
/*

*/


#include <iostream>
#include <fstream>
#include <vector>
#include <queue>
#include <unordered_map>
#include <map>
#include <string>
#include <iomanip>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <ctime>
#include <deque>

#define INF 2140000000
#define MaxN 10005

using namespace std;

int N,M,K,Source,Dest=-1,cost[MaxN];
deque <short> Q;
struct light
{
short x,y;
}v[MaxN];
vector<pair<short,bool> >Graph[MaxN];
void BFS(int node)
{
	Q.push_back(node);
	for(int i=1;i<=K;i++)
		cost[i]=INF;
	cost[node]=0;
	while(!Q.empty())
	{
		node=Q.front();
		Q.pop_front();
		for(int i=0;i<Graph[node].size();i++)
		{
			if(cost[Graph[node][i].first]>cost[node]+Graph[node][i].second)
			{
				cost[Graph[node][i].first]=cost[node]+Graph[node][i].second;
				if(Graph[node][i].second==0)
					Q.push_front(Graph[node][i].first);
				else Q.push_back(Graph[node][i].first);
			}
		}
	}
}
int main()
{
	cin>>N>>M>>K;
	for(int i=1;i<=K;i++)
	{
		cin>>v[i].x>>v[i].y;
		if(v[i].x==1&&v[i].y==1)
			Source=i;
		if(v[i].x==N&&v[i].y==M)
			Dest=i;
	}
	for(int i=1;i<=K;i++)
		for(int j=i+1;j<=K;j++)
		{
			int dx=abs(v[i].x-v[j].x),dy=abs(v[i].y-v[j].y);
			if(dx+dy==1)
				Graph[i].push_back(make_pair(j,0)),Graph[j].push_back(make_pair(i,0));
			else if(min(dx,dy)<=2)
				Graph[i].push_back(make_pair(j,1)),Graph[j].push_back(make_pair(i,1));
		}
	if(Dest==-1)
	{
		v[K+1].x=N+1,v[K+1].y=M;
		for(int i=1;i<=K;i++)
		{
			int dx=(N-v[i].x),dy=M-v[i].y;
			if(dx<=1||dy<=1)
				Graph[K+1].push_back(make_pair(i,1)),Graph[i].push_back(make_pair(K+1,1));
		}
		Dest=K+1;
		K++;
	}
	BFS(Source);
	if(cost[Dest]==INF)
		cout<<"-1";
	else cout<< cost[Dest];
	return 0;
}


#include <iostream>
#include <fstream>
#include <vector>
#include <queue>
#include <unordered_map>
#include <map>
#include <string>
#include <iomanip>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <ctime>
#include <deque>

#define INF 2140000000
#define MaxN 10005

using namespace std;

int N,M,K,Source,Dest=-1,cost[MaxN];
bool found[MaxN];
deque <int> Q;
struct light
{
int x,y;
}v[MaxN];
vector<pair<int,int> >Graph[MaxN];
void BFS(int node)
{
	Q.push_back(node);
	for(int i=1;i<=K;i++)
		cost[i]=INF;
	cost[node]=0;
	while(!Q.empty())
	{
		node=Q.front();
		Q.pop_front();
		for(int i=0;i<Graph[node].size();i++)
		{
			if(cost[Graph[node][i].first]>cost[node]+Graph[node][i].second)
			{
				cost[Graph[node][i].first]=cost[node]+Graph[node][i].second;
				if(Graph[node][i].second==0)
					Q.push_front(Graph[node][i].first);
				else Q.push_back(Graph[node][i].first);
			}
		}
	}
}
int main()
{
	cin>>N>>M>>K;
	for(int i=1;i<=K;i++)
	{
		cin>>v[i].x>>v[i].y;
		if(v[i].x==1&&v[i].y==1)
			Source=i;
		if(v[i].x==N&&v[i].y==M)
			Dest=i;
	}
	for(int i=1;i<=K;i++)
		for(int j=i+1;j<=K;j++)
		{
			int dx=abs(v[i].x-v[j].x),dy=abs(v[i].y-v[j].y);
			if(dx+dy==1)
				Graph[i].push_back(make_pair(j,0)),Graph[j].push_back(make_pair(i,0));
			else if(min(dx,dy)<=2)
				Graph[i].push_back(make_pair(j,1)),Graph[j].push_back(make_pair(i,1));
		}
	if(Dest==-1)
	{
		v[K+1].x=N+1,v[K+1].y=M;
		for(int i=1;i<=K;i++)
		{
			int dx=(N-v[i].x),dy=M-v[i].y;
			if(dx<=1||dy<=1)
				Graph[K+1].push_back(make_pair(i,1)),Graph[i].push_back(make_pair(K+1,1));
		}
		Dest=K+1;
		K++;
	}
	BFS(Source);
	if(cost[Dest]==INF)
		cout<<"-1";
	else cout<< cost[Dest];
	return 0;
}


#include<set>
#include<map>
#include<list>
#include<queue>
#include<stack>
#include<string>
#include<time.h>
#include<math.h>
#include<memory>
#include<vector>
#include<bitset>
#include<fstream>
#include<stdio.h>
#include<utility>
#include<string.h>
#include<iostream>
#include<stdlib.h>
#include<algorithm>
using namespace std;
int dist[20005];
bool vis[20005];
bitset<20005> b[10005];
int x[20005],y[20005];
int k;
void bfs(int s)
{
    static int que[20005];
    static int que2[20005];
    int front=0,rail=1;
    que[0]=s;
    dist[s]=0;
    int f2=0,r2=0;
    for (;;)
    {
        for (;front<rail;front++)
        {
            int now=que[front];
            if (now==k) return;
            if (vis[now]) continue;
            vis[now]=true;
            int i;
            for (i=0;i<=k;i++)
            {
                if ((dist[i]!=-1)&&(dist[i]<=dist[now])) continue;
                if (b[now][i*2+1]==1)
                {
                    dist[i]=dist[now];
                    que[rail++]=i;
                    continue;
                }
                if (dist[i]==dist[now]+1) continue;
                if (b[now][i*2]==1)
                {
                    dist[i]=dist[now]+1;
                    que2[r2++]=i;
                }
            }
        }
        if (r2==0) break;
        for (;f2<r2;f2++)
        {
            que[rail++]=que2[f2];
        }
        f2=0;
        r2=0;
    }
}
int main()
{
    #ifdef absi2011
    freopen("input.txt","r",stdin);
    freopen("output.txt","w",stdout);
    #endif
    int n,m;
    scanf("%d%d%d",&n,&m,&k);
    int i;
    int s=0;
    for (i=0;i<k;i++)
    {
        scanf("%d%d",&x[i],&y[i]);
        if ((x[i]==1)&&(y[i]==1)) s=i;
        int j;
        for (j=0;j<i;j++)
        {
            if (((x[i]-x[j]<=2)&&(x[j]-x[i]<=2))||((y[i]-y[j]<=2)&&(y[j]-y[i]<=2)))
            {
                b[i][j*2]=1;
                b[j][i*2]=1;
            }
            if (((x[i]-x[j]==1)||(x[j]-x[i]==1))&&(y[i]==y[j]))
            {
                b[i][j*2+1]=1;
                b[j][i*2+1]=1;
            }
            if (((y[i]-y[j]==1)||(y[j]-y[i]==1))&&(x[i]==x[j]))
            {
                b[i][j*2+1]=1;
                b[j][i*2+1]=1;
            }
        }
        if (x[i]>=n-1)
        {
            b[i][k*2]=1;
        }
        if (y[i]>=m-1)
        {
            b[i][k*2]=1;
        }
        if ((x[i]==n)&&(y[i]==m))
        {
            b[i][k*2+1]=1;
        }
    }
    memset(dist,-1,sizeof(dist));
    memset(vis,false,sizeof(vis));
    bfs(s);
    printf("%d\n",dist[k]);
    return 0;
}


#include<set>
#include<map>
#include<list>
#include<queue>
#include<stack>
#include<string>
#include<time.h>
#include<math.h>
#include<memory>
#include<vector>
#include<bitset>
#include<fstream>
#include<stdio.h>
#include<utility>
#include<string.h>
#include<iostream>
#include<stdlib.h>
#include<algorithm>
using namespace std;
int dist[10005];
bool vis[10005];
bitset<20005> b[10005];
int x[10005],y[10005];
int k;
void bfs(int s)
{
    static int que[20005];
    static int que2[10005];
    int front=0,rail=1;
    que[0]=s;
    dist[s]=0;
    int f2=0,r2=0;
    for (;;)
    {
        for (;front<rail;front++)
        {
            int now=que[front];
            if (now==k) return;
            if (vis[now]) continue;
            vis[now]=true;
            int i;
            for (i=0;i<=k;i++)
            {
                if (dist[i]==dist[now]) continue;
                if (b[now][i*2+1]==1)
                {
                    dist[i]=dist[now];
                    que[rail++]=i;
                    continue;
                }
                if (dist[i]==dist[now]+1) continue;
                if (b[now][i*2]==1)
                {
                    dist[i]=dist[now]+1;
                    que2[r2++]=i;
                }
            }
        }
        if (r2==0) break;
        for (;f2<r2;f2++)
        {
            que[rail++]=que2[f2];
        }
        f2=0;
        r2=0;
    }
}
int main()
{
    #ifdef absi2011
    freopen("input.txt","r",stdin);
    freopen("output.txt","w",stdout);
    #endif
    int n,m;
    scanf("%d%d%d",&n,&m,&k);
    int i;
    int s=0;
    for (i=0;i<k;i++)
    {
        scanf("%d%d",&x[i],&y[i]);
        if ((x[i]==1)&&(y[i]==1)) s=i;
        int j;
        for (j=0;j<i;j++)
        {
            if (((x[i]-x[j]<=2)&&(x[j]-x[i]<=2))||((y[i]-y[j]<=2)&&(y[j]-y[i]<=2)))
            {
                b[i][j*2]=1;
                b[j][i*2]=1;
            }
            if (((x[i]-x[j]==1)||(x[j]-x[i]==1))&&(y[i]==y[j]))
            {
                b[i][j*2+1]=1;
                b[j][i*2+1]=1;
            }
            if (((y[i]-y[j]==1)||(y[j]-y[i]==1))&&(x[i]==x[j]))
            {
                b[i][j*2+1]=1;
                b[j][i*2+1]=1;
            }
        }
        if (x[i]>=n-1)
        {
            b[i][k*2]=1;
        }
        if (x[j]>=m-1)
        {
            b[i][k*2]=1;
        }
        if ((x[i]==n)&&(y[i]==m))
        {
            b[i][k*2+1]=1;
        }
    }
    memset(dist,-1,sizeof(dist));
    memset(vis,false,sizeof(vis));
    bfs(s);
    printf("%d\n",dist[k]);
    return 0;
}


#include<set>
#include<map>
#include<list>
#include<queue>
#include<stack>
#include<string>
#include<time.h>
#include<math.h>
#include<memory>
#include<vector>
#include<bitset>
#include<fstream>
#include<stdio.h>
#include<utility>
#include<string.h>
#include<iostream>
#include<stdlib.h>
#include<algorithm>
using namespace std;
int dist[20005];
bool vis[20005];
bitset<20005> b[10005];
int x[20005],y[20005];
int k;
void bfs(int s)
{
    static int que[20005];
    static int que2[20005];
    int front=0,rail=1;
    que[0]=s;
    dist[s]=0;
    int f2=0,r2=0;
    for (;;)
    {
        for (;front<rail;front++)
        {
            int now=que[front];
            if (now==k) return;
            if (vis[now]) continue;
            vis[now]=true;
            int i;
            for (i=0;i<=k;i++)
            {
                if ((dist[i]!=-1)&&(dist[i]<=dist[now])) continue;
                if (b[now][i*2+1]==1)
                {
                    dist[i]=dist[now];
                    que[rail++]=i;
                    continue;
                }
                if (dist[i]==dist[now]+1) continue;
                if (b[now][i*2]==1)
                {
                    dist[i]=dist[now]+1;
                    que2[r2++]=i;
                }
            }
        }
        if (r2==0) break;
        for (;f2<r2;f2++)
        {
            que[rail++]=que2[f2];
        }
        f2=0;
        r2=0;
    }
}
int main()
{
    #ifdef absi2011
    freopen("input.txt","r",stdin);
    freopen("output.txt","w",stdout);
    #endif
    int n,m;
    scanf("%d%d%d",&n,&m,&k);
    int i;
    int s=0;
    for (i=0;i<k;i++)
    {
        scanf("%d%d",&x[i],&y[i]);
        if ((x[i]==1)&&(y[i]==1)) s=i;
        int j;
        for (j=0;j<i;j++)
        {
            if (((x[i]-x[j]<=2)&&(x[j]-x[i]<=2))||((y[i]-y[j]<=2)&&(y[j]-y[i]<=2)))
            {
                b[i][j*2]=1;
                b[j][i*2]=1;
            }
            if (((x[i]-x[j]==1)||(x[j]-x[i]==1))&&(y[i]==y[j]))
            {
                b[i][j*2+1]=1;
                b[j][i*2+1]=1;
            }
            if (((y[i]-y[j]==1)||(y[j]-y[i]==1))&&(x[i]==x[j]))
            {
                b[i][j*2+1]=1;
                b[j][i*2+1]=1;
            }
        }
        if (x[i]>=n-1)
        {
            b[i][k*2]=1;
        }
        if (x[j]>=m-1)
        {
            b[i][k*2]=1;
        }
        if ((x[i]==n)&&(y[i]==m))
        {
            b[i][k*2+1]=1;
        }
    }
    memset(dist,-1,sizeof(dist));
    memset(vis,false,sizeof(vis));
    bfs(s);
    printf("%d\n",dist[k]);
    return 0;
}


#include<set>
#include<map>
#include<list>
#include<queue>
#include<stack>
#include<string>
#include<time.h>
#include<math.h>
#include<memory>
#include<vector>
#include<bitset>
#include<fstream>
#include<stdio.h>
#include<utility>
#include<string.h>
#include<iostream>
#include<stdlib.h>
#include<algorithm>
using namespace std;
int dist[20005];
bool vis[20005];
bitset<20005> b[10005];
int x[20005],y[20005];
int k;
void bfs(int s)
{
    static int que[20005];
    static int que2[20005];
    int front=0,rail=1;
    que[0]=s;
    dist[s]=0;
    int f2=0,r2=0;
    for (;;)
    {
        for (;front<rail;front++)
        {
            int now=que[front];
            if (now==k) return;
            if (vis[now]) continue;
            vis[now]=true;
            int i;
            for (i=0;i<=k;i++)
            {
                if (dist[i]==dist[now]) continue;
                if (b[now][i*2+1]==1)
                {
                    dist[i]=dist[now];
                    que[rail++]=i;
                    continue;
                }
                if (dist[i]==dist[now]+1) continue;
                if (b[now][i*2]==1)
                {
                    dist[i]=dist[now]+1;
                    que2[r2++]=i;
                }
            }
        }
        if (r2==0) break;
        for (;f2<r2;f2++)
        {
            que[rail++]=que2[f2];
        }
        f2=0;
        r2=0;
    }
}
int main()
{
    #ifdef absi2011
    freopen("input.txt","r",stdin);
    freopen("output.txt","w",stdout);
    #endif
    int n,m;
    scanf("%d%d%d",&n,&m,&k);
    int i;
    int s=0;
    for (i=0;i<k;i++)
    {
        scanf("%d%d",&x[i],&y[i]);
        if ((x[i]==1)&&(y[i]==1)) s=i;
        int j;
        for (j=0;j<i;j++)
        {
            if (((x[i]-x[j]<=2)&&(x[j]-x[i]<=2))||((y[i]-y[j]<=2)&&(y[j]-y[i]<=2)))
            {
                b[i][j*2]=1;
                b[j][i*2]=1;
            }
            if (((x[i]-x[j]==1)||(x[j]-x[i]==1))&&(y[i]==y[j]))
            {
                b[i][j*2+1]=1;
                b[j][i*2+1]=1;
            }
            if (((y[i]-y[j]==1)||(y[j]-y[i]==1))&&(x[i]==x[j]))
            {
                b[i][j*2+1]=1;
                b[j][i*2+1]=1;
            }
        }
        if (x[i]>=n-1)
        {
            b[i][k*2]=1;
        }
        if (x[j]>=m-1)
        {
            b[i][k*2]=1;
        }
        if ((x[i]==n)&&(y[i]==m))
        {
            b[i][k*2+1]=1;
        }
    }
    memset(dist,-1,sizeof(dist));
    memset(vis,false,sizeof(vis));
    bfs(s);
    printf("%d\n",dist[k]);
    return 0;
}


from sys import stdin
from collections import deque
def main():
    n, m, k = map(int, stdin.readline().split())
    a = [map(int, stdin.readline().split()) for _ in xrange(k)]
    row = [dict() for i in xrange(n + 10)]
    col = [dict() for i in xrange(m + 10)]
    inf = 10010001
    d = [inf] * k
    q = []
    pu = q.append
    for i in xrange(k):
        r, c = a[i]
        row[r][c] = i
        col[c][r] = i
        if r == c == 1:
            d[i] = 0
            pu(i)
    done = [None] * k
    while q:
        v = []
        for x in q:
            r, c = a[x]
            qq = deque()
            qq.append(x)
            done[x] = 1
            while qq:
                y = qq.popleft()
                r, c = a[y]
                for cc in (c-1, c+1):
                    if cc in row[r] and done[row[r][cc]] is None:
                        z = row[r][cc]
                        done[z] = 1
                        qq.append(z)
                for rr in (r-1, r+1):
                    if rr in col[c] and done[col[c][rr]] is None:
                        z = col[c][rr]
                        done[z] = 1
                        qq.append(z)
                d[y] = d[x]
                v.append(y)
        sr = set()
        sc = set()
        del q[:]
        for x in v:
            r, c = a[x]
            for rr in xrange(r - 2, r + 3):
                sr.add(rr)
            for cc in xrange(c - 2, c + 3):
                sc.add(cc)
        for i in sr:
            for j in row[i].viewvalues():
                if d[j] == inf:
                    d[j] = d[x] + 1
                    pu(j)
            row[i] = {}
        for i in sc:
            for j in col[i].viewvalues():
                if d[j] == inf:
                    d[j] = d[x] + 1
                    pu(j)
            col[i] = {}
    ans = inf
    for i in xrange(k):
        r, c = a[i]
        if r == n and c == m:
            if ans > d[i]:
                ans = d[i]
        if r >= n - 1:
            if ans > d[i] + 1:
                ans = d[i] + 1
        if c >= m - 1:
            if ans > d[i] + 1:
                ans = d[i] + 1
    if ans == inf:
        print -1
    else:
        print ans
main()


from sys import stdin
from collections import deque
def main():
    n, m, k = map(int, stdin.readline().split())
    a = [map(int, stdin.readline().split()) for _ in xrange(k)]
    row = [dict() for i in xrange(n + 10)]
    col = [dict() for i in xrange(m + 10)]
    inf = 10010001
    d = [inf] * k
    q = []
    pu = q.append
    for i in xrange(k):
        r, c = a[i]
        row[r][c] = i
        col[c][r] = i
        if r == c == 1:
            d[i] = 0
            pu(i)
    done = [None] * k
    while q:
        v = []
        for x in q:
            r, c = a[x]
            qq = deque()
            qq.append(x)
            done[x] = 1
            while qq:
                y = qq.popleft()
                r, c = a[y]
                for cc in (c-1, c+1):
                    if cc in row[r] and done[row[r][cc]] is None:
                        z = row[r][cc]
                        done[z] = 1
                        qq.append(z)
                for rr in (r-1, r+1):
                    if rr in col[c] and done[col[c][rr]] is None:
                        z = col[c][rr]
                        done[z] = 1
                        qq.append(z)
                d[y] = d[x]
                v.append(y)
        sr = set()
        sc = set()
        del q[:]
        for x in v:
            r, c = a[x]
            for rr in xrange(r - 2, r + 3):
                sr.add(rr)
            for cc in xrange(c - 2, c + 3):
                sc.add(cc)
        for i in sr:
            for j in row[i].viewvalues():
                if d[j] == inf:
                    d[j] = d[x] + 1
                    pu(j)
            row[i] = {}
        for j in sc:
            for j in col[i].viewvalues():
                if d[j] == inf:
                    d[j] = d[x] + 1
                    pu(j)
            col[i] = {}
    ans = inf
    for i in xrange(k):
        r, c = a[i]
        if r == n and c == m:
            if ans > d[i]:
                ans = d[i]
        if r >= n - 1:
            if ans > d[i] + 1:
                ans = d[i] + 1
        if c >= m - 1:
            if ans > d[i] + 1:
                ans = d[i] + 1
    if ans == inf:
        print -1
    else:
        print ans
main()


from sys import stdin
from collections import deque
def main():
    n, m, k = map(int, stdin.readline().split())
    a = [map(int, stdin.readline().split()) for _ in xrange(k)]
    row = [[] for i in xrange(n + 10)]
    col = [[] for i in xrange(m + 10)]
    inf = 10010001
    d = [inf] * k
    q = deque()
    pu = q.append
    for i in xrange(k):
        r, c = a[i]
        row[r].append(i)
        col[c].append(i)
        if r == c == 1:
            d[i] = 0
            pu(i)
    po = q.popleft
    while q:
        x = po()
        r, c = a[x]
        for i in xrange(r - 2, r + 2):
            for j in row[i]:
                if d[j] == inf:
                    d[j] = d[x] + 1
                    pu(j)
            row[i] = []
        for i in xrange(c - 2, c + 2):
            for j in col[i]:
                if d[j] == inf:
                    d[j] = d[x] + 1
                    pu(j)
            col[i] = []
    ans = inf
    for i in xrange(k):
        r, c = a[i]
        if r == n and c == m:
            if ans > d[i]:
                ans = d[i]
        if r >= n - 1:
            if ans > d[i] + 1:
                ans = d[i] + 1
        if c >= m - 1:
            if ans > d[i] + 1:
                ans = d[i] + 1
    if ans == inf:
        print -1
    else:
        print ans
main()


from sys import stdin
from collections import deque
def main():
    n, m, k = map(int, stdin.readline().split())
    a = [map(int, stdin.readline().split()) for _ in xrange(k)]
    row = [dict() for i in xrange(n + 10)]
    col = [dict() for i in xrange(m + 10)]
    inf = 10010001
    d = [inf] * k
    q = deque()
    pu = q.append
    for i in xrange(k):
        r, c = a[i]
        row[r][c] = i
        col[c][r] = i
        if r == c == 1:
            d[i] = 0
            pu(i)
    done = [None] * k
    po = q.popleft
    while q:
        x = po()
        r, c = a[x]
        v = []
        qq = deque()
        qq.append(x)
        done[x] = 1
        while qq:
            y = qq.popleft()
            r, c = a[y]
            for cc in (c-1, c+1):
                if cc in row[r] and done[row[r][cc]] is None:
                    z = row[r][cc]
                    done[z] = 1
                    qq.append(z)
            for rr in (r-1, r+1):
                if rr in col[c] and done[col[c][rr]] is None:
                    z = col[c][rr]
                    done[z] = 1
                    qq.append(z)
            d[y] = d[x]
            v.append(y)
        for x in v:
            r, c = a[x]
            for i in xrange(r - 2, r + 2):
                for j in row[i].viewvalues():
                    if d[j] == inf:
                        d[j] = d[x] + 1
                        pu(j)
                row[i] = {}
            for i in xrange(c - 2, c + 2):
                for j in col[i].viewvalues():
                    if d[j] == inf:
                        d[j] = d[x] + 1
                        pu(j)
                col[i] = {}
    ans = inf
    for i in xrange(k):
        r, c = a[i]
        if r == n and c == m:
            if ans > d[i]:
                ans = d[i]
        if r >= n - 1:
            if ans > d[i] + 1:
                ans = d[i] + 1
        if c >= m - 1:
            if ans > d[i] + 1:
                ans = d[i] + 1
    if ans == inf:
        print -1
    else:
        print ans
main()


n,m,k=[int(i) for i in raw_input().split(" ")]
t={}
nbg=0
dbg={}
rg={}
rrg={}

#for i in range(len(t)):
#    t[i]=[0]*(m+2)

def neighbourslit(r,c):
    res=[]
    for ii in [(r-1,c),(r+1,c),(r,c-1),(r,c+1)]:
        if ii in t:
            res+=[[ii[0],ii[1],rg[t[ii[0],ii[1]]]]]
    return res

for i in range(k):
    r,c=[int(j) for j in raw_input().split(" ")]
    nbs=neighbourslit(r,c)
    if len(nbs)==0:
        nbg+=1
        t[r,c]=nbg
        dbg[nbg]=[(r,c)]
        rg[nbg]=nbg
        rrg[nbg]=[nbg]
    else:
        myg=nbs[0][2]
        t[r,c]=myg
        dbg[myg]+=[(r,c)]
        for j in range(1,len(nbs)):
            oldg=rg[t[nbs[j][0],nbs[j][1]]]
            if myg!=oldg:
                rrg[myg]+=rrg[oldg]
                for g in rrg[oldg]:
                    rg[g]=myg
                del rrg[oldg]
                dbg[myg]+=dbg[oldg]
                del dbg[oldg]

#print "nb groupes : {} pour {} lampes".format(len(dbg),k)

#maxandmincolsofgroups
mrc={}
for gm in dbg.keys():
    minr=n+1
    maxr=0
    minc=m+1
    maxc=0
    for i in dbg[gm]:
        r=i[0]
        c=i[1]
        minr=min(minr,r)
        maxr=max(maxr,r)
        minc=min(minc,c)
        maxc=max(maxc,c)
        mrc[gm]=[minr,maxr,minc,maxc]

dt={}

def touch(a,b):
    am=min(a,b)
    b=a+b-am
    a=am
    if (a,b) in dt:
        return dt[a,b]
    else:
        dt[a,b]=((mrc[a][2]<=mrc[b][3]+2) and (mrc[b][2]<=mrc[a][3]+2)) or ((mrc[a][0]<=mrc[b][1]+2) and (mrc[b][0]<=mrc[a][1]+2))
        return dt[a,b]

toreach=rg[t[1,1]]
resg={}
toassign=dict(zip(dbg.keys(),[0]*len(dbg)))

def listgroupsinroworcols(rows="All",cols="All"):
    lights=[]
    if rows!="All":
        lights+=[i for i in t.keys() if i[0] in range(rows[0],rows[1]+1)]
    if cols!="All":
        lights+=[i for i in t.keys() if i[1] in range(cols[0],cols[1]+1)]
    dr={}
    for g in lights:
        gg=rg[t[g]]
        if gg not in dr:
            dr[gg]=0
    return dr.keys()

minpay=None
if (n,m) in  t:
    gg=rg[t[n,m]]
    resg[gg]=0
    minpay=0
else:
    for i in range(n):
        if (i,m) in t:
            resg[rg[t[i,m]]]=1
            minpay=1
        if (i,m-1) in t:
            resg[rg[t[i,m-1]]]=1
            minpay=1
    for i in range(m):
        if (n,i) in t:
            resg[rg[t[n,i]]]=1
            minpay=1
        if (n-1,i) in t:
            resg[rg[t[n-1,i]]]=1
            minpay=1

nr=resg.keys()
for i in resg.keys():
    del toassign[i]
while toreach not in resg and len(nr)>0:
    nnr=[]
    for gm in nr:
#        for i in toassign.keys():
#            if touch(gm,i):
#                nnr+=[i]
#                resg[i]=resg[gm]+1
#                del toassign[i]
        ng=listgroupsinroworcols((mrc[gm][0]-1,mrc[gm][1]+1),(mrc[gm][2]-1,mrc[gm][3]+1))
        nng=[i for i in ng if i in toassign]
        nnr+=nng
        for i in nng:
            nnr+=[i]
            resg[i]=resg[gm]+1
            del toassign[i]
    nr=nnr

if toreach not in resg:
    print -1
else:
    print resg[toreach]
#print res


n,m,k=[int(i) for i in raw_input().split(" ")]
t={}
nbg=0
dbg={}
rg={}
rrg={}

#for i in range(len(t)):
#    t[i]=[0]*(m+2)

def neighbourslit(r,c):
    res=[]
    for ii in [(r-1,c),(r+1,c),(r,c-1),(r,c+1)]:
        if ii in t:
            res+=[[ii[0],ii[1],rg[t[ii[0],ii[1]]]]]
    return res

for i in range(k):
    r,c=[int(j) for j in raw_input().split(" ")]
    nbs=neighbourslit(r,c)
    if len(nbs)==0:
        nbg+=1
        t[r,c]=nbg
        dbg[nbg]=[(r,c)]
        rg[nbg]=nbg
        rrg[nbg]=[nbg]
    else:
        myg=nbs[0][2]
        t[r,c]=myg
        dbg[myg]+=[(r,c)]
        for j in range(1,len(nbs)):
            oldg=rg[t[nbs[j][0],nbs[j][1]]]
            if myg!=oldg:
                rrg[myg]+=rrg[oldg]
                for g in rrg[oldg]:
                    rg[g]=myg
                del rrg[oldg]
                dbg[myg]+=dbg[oldg]
                del dbg[oldg]

#print "nb groupes : {} pour {} lampes".format(len(dbg),k)

#maxandmincolsofgroups
mrc={}
for gm in dbg.keys():
    minr=n+1
    maxr=0
    minc=m+1
    maxc=0
    for i in dbg[gm]:
        r=i[0]
        c=i[1]
        minr=min(minr,r)
        maxr=max(maxr,r)
        minc=min(minc,c)
        maxc=max(maxc,c)
        mrc[gm]=[minr,maxr,minc,maxc]

dt={}

def touch(a,b):
    am=min(a,b)
    b=a+b-am
    a=am
    if (a,b) in dt:
        return dt[a,b]
    else:
        dt[a,b]=((mrc[a][2]<=mrc[b][3]+2) and (mrc[b][2]<=mrc[a][3]+2)) or ((mrc[a][0]<=mrc[b][1]+2) and (mrc[b][0]<=mrc[a][1]+2))
        return dt[a,b]

toreach=rg[t[1,1]]
resg={}
toassign=dict(zip(dbg.keys(),[0]*len(dbg)))

def listgroupsinroworcols(rows="All",cols="All"):
    lights=[]
    if rows!="All":
        lights+=[i for i in t.keys() if i[0] in range(rows[0],rows[1]+1)]
    if cols!="All":
        lights+=[i for i in t.keys() if i[1] in range(cols[0],cols[1]+1)]
    dr={}
    for g in lights:
        gg=rg[t[g]]
        if gg not in dr:
            dr[gg]=0
    return dr.keys()

minpay=None
if (n,m) in  t:
    gg=rg[t[n,m]]
    resg[gg]=0
    minpay=0
else:
    for i in range(n):
        if (i,m) in t:
            resg[rg[t[i,m]]]=1
            minpay=1
        if (i,m-1) in t:
            resg[rg[t[i,m-1]]]=1
            minpay=1
    for i in range(m):
        if (n,i) in t:
            resg[rg[t[n,i]]]=1
            minpay=1
        if (n-1,i) in t:
            resg[rg[t[n-1,i]]]=1
            minpay=1

nr=resg.keys()
for i in resg.keys():
    del toassign[i]
while toreach not in resg and len(nr)>0:
    nnr=[]
    for gm in nr:
#        for i in toassign.keys():
#            if touch(gm,i):
#                nnr+=[i]
#                resg[i]=resg[gm]+1
#                del toassign[i]
        ng=listgroupsinroworcols((mrc[gm][0]-2,mrc[gm][1]+2),(mrc[gm][2]-2,mrc[gm][3]+2))
        nng=[i for i in ng if i in toassign]
        nnr+=nng
        for i in nng:
            nnr+=[i]
            resg[i]=resg[gm]+1
            del toassign[i]
    nr=nnr

if toreach not in resg:
    print -1
else:
    print resg[toreach]
#print res


n,m,k=[int(i) for i in raw_input().split(" ")]
t=[0]*(n+2)
nbg=0
dbg={}
rg={}
rrg={}

for i in range(len(t)):
    t[i]=[0]*(m+2)

def neighbourslit(r,c):
    res=[]
    for ii in [(r-1,c),(r+1,c),(r,c-1),(r,c+1)]:
        if t[ii[0]][ii[1]]>0:
            res+=[[ii[0],ii[1],rg[t[ii[0]][ii[1]]]]]
    return res

for i in range(k):
    r,c=[int(j) for j in raw_input().split(" ")]
    nbs=neighbourslit(r,c)
    if len(nbs)==0:
        nbg+=1
        t[r][c]=nbg
        dbg[nbg]=[(r,c)]
        rg[nbg]=nbg
        rrg[nbg]=[nbg]
    else:
        myg=nbs[0][2]
        t[r][c]=myg
        dbg[myg]+=[(r,c)]
        for j in range(1,len(nbs)):
            oldg=rg[t[nbs[j][0]][nbs[j][1]]]
            if myg!=oldg:
                rrg[myg]+=rrg[oldg]
                for g in rrg[oldg]:
                    rg[g]=myg
                del rrg[oldg]
                dbg[myg]+=dbg[oldg]
                del dbg[oldg]

#print "nb groupes : {} pour {} lampes".format(len(dbg),k)

#maxandmincolsofgroups
mrc={}
for gm in dbg.keys():
    minr=n+1
    maxr=0
    minc=m+1
    maxc=0
    for i in dbg[gm]:
        r=i[0]
        c=i[1]
        minr=min(minr,r)
        maxr=max(maxr,r)
        minc=min(minc,c)
        maxc=max(maxc,c)
        mrc[gm]=[minr,maxr,minc,maxc]

dt={}
def touch(a,b):
    am=min(a,b)
    b=a+b-am
    a=am
    if (a,b) in dt:
        return dt[a,b]
    else:
        dt[a,b]=((mrc[a][2]<=mrc[b][3]+2) and (mrc[b][2]<=mrc[a][3]+2)) or ((mrc[a][0]<=mrc[b][1]+2) and (mrc[b][0]<=mrc[a][1]+2))
        return dt[a,b]

toreach=rg[t[1][1]]
resg={}
toassign=dict(zip(dbg.keys(),[0]*len(dbg)))
minpay=None
if t[n][m]>0:
    gg=rg[t[n][m]]
    resg[gg]=0
    minpay=0
else:
    for i in range(n):
        if t[i][m]>0:
            resg[rg[t[i][m]]]=1
            minpay=1
        if t[i][m-1]>0:
            resg[rg[t[i][m-1]]]=1
            minpay=1
    for i in range(m):
        if t[n][i]>0:
            resg[rg[t[n][i]]]=1
            minpay=1
        if t[n-1][i]>0:
            resg[rg[t[n-1][i]]]=1
            minpay=1

nr=resg.keys()
for i in resg.keys():
    del toassign[i]
while toreach not in resg and len(nr)>0:
    nnr=[]
    for gm in nr:
        for i in toassign.keys():
            if touch(gm,i):
                nnr+=[i]
                resg[i]=resg[gm]+1
                del toassign[i]
    nr=nnr

if toreach not in resg:
    print -1
else:
    print resg[toreach]
#print res


n,m,k=[int(i) for i in raw_input().split(" ")]
t={}
nbg=0
dbg={}
rg={}
rrg={}

#for i in range(len(t)):
#    t[i]=[0]*(m+2)

def neighbourslit(r,c):
    res=[]
    for ii in [(r-1,c),(r+1,c),(r,c-1),(r,c+1)]:
        if ii in t:
            res+=[[ii[0],ii[1],rg[t[ii[0],ii[1]]]]]
    return res

for i in range(k):
    r,c=[int(j) for j in raw_input().split(" ")]
    nbs=neighbourslit(r,c)
    if len(nbs)==0:
        nbg+=1
        t[r,c]=nbg
        dbg[nbg]=[(r,c)]
        rg[nbg]=nbg
        rrg[nbg]=[nbg]
    else:
        myg=nbs[0][2]
        t[r,c]=myg
        dbg[myg]+=[(r,c)]
        for j in range(1,len(nbs)):
            oldg=rg[t[nbs[j][0],nbs[j][1]]]
            if myg!=oldg:
                rrg[myg]+=rrg[oldg]
                for g in rrg[oldg]:
                    rg[g]=myg
                del rrg[oldg]
                dbg[myg]+=dbg[oldg]
                del dbg[oldg]

#print "nb groupes : {} pour {} lampes".format(len(dbg),k)

#maxandmincolsofgroups
mrc={}
for gm in dbg.keys():
    minr=n+1
    maxr=0
    minc=m+1
    maxc=0
    for i in dbg[gm]:
        r=i[0]
        c=i[1]
        minr=min(minr,r)
        maxr=max(maxr,r)
        minc=min(minc,c)
        maxc=max(maxc,c)
        mrc[gm]=[minr,maxr,minc,maxc]

dt={}
def touch(a,b):
    am=min(a,b)
    b=a+b-am
    a=am
    if (a,b) in dt:
        return dt[a,b]
    else:
        dt[a,b]=((mrc[a][2]<=mrc[b][3]+2) and (mrc[b][2]<=mrc[a][3]+2)) or ((mrc[a][0]<=mrc[b][1]+2) and (mrc[b][0]<=mrc[a][1]+2))
        return dt[a,b]

toreach=rg[t[1,1]]
resg={}
toassign=dict(zip(dbg.keys(),[0]*len(dbg)))
minpay=None
if (n,m) in  t:
    gg=rg[t[n,m]]
    resg[gg]=0
    minpay=0
else:
    for i in range(n):
        if (i,m) in t:
            resg[rg[t[i,m]]]=1
            minpay=1
        if (i,m-1) in t:
            resg[rg[t[i,m-1]]]=1
            minpay=1
    for i in range(m):
        if (n,i) in t:
            resg[rg[t[n,i]]]=1
            minpay=1
        if (n-1,i) in t:
            resg[rg[t[n-1,i]]]=1
            minpay=1

nr=resg.keys()
for i in resg.keys():
    del toassign[i]
while toreach not in resg and len(nr)>0:
    nnr=[]
    for gm in nr:
        for i in toassign.keys():
            if touch(gm,i):
                nnr+=[i]
                resg[i]=resg[gm]+1
                del toassign[i]
    nr=nnr

if toreach not in resg:
    print -1
else:
    print resg[toreach]
#print res


n,m,k=[int(i) for i in raw_input().split(" ")]
t=[0]*(n+2)
nbg=0
dbg={}
rg={}

for i in range(len(t)):
    t[i]=[0]*(m+2)

def neighbourslit(r,c):
    res=[]
    for ii in [(r-1,c),(r+1,c),(r,c-1),(r,c+1)]:
        if t[ii[0]][ii[1]]>0:
            res+=[[ii[0],ii[1],rg[t[ii[0]][ii[1]]]]]
    return res

for i in range(k):
    r,c=[int(j) for j in raw_input().split(" ")]
    nbs=neighbourslit(r,c)
    if len(nbs)==0:
        nbg+=1
        t[r][c]=nbg
        dbg[nbg]=[(r,c)]
        rg[nbg]=nbg
    else:
        myg=nbs[0][2]
        t[r][c]=myg
        dbg[myg]+=[(r,c)]
        for j in range(1,len(nbs)):
            oldg=rg[t[nbs[j][0]][nbs[j][1]]]
            if myg!=oldg:
                rg[t[nbs[j][0]][nbs[j][1]]]=myg
                dbg[myg]+=dbg[oldg]
                del dbg[oldg]

#print "nb groupes : {} pour {} lampes".format(len(dbg),k)

#maxandmincolsofgroups
mrc={}
for gm in dbg.keys():
    minr=n+1
    maxr=0
    minc=m+1
    maxc=0
    for i in dbg[gm]:
        r=i[0]
        c=i[1]
        minr=min(minr,r)
        maxr=max(maxr,r)
        minc=min(minc,c)
        maxc=max(maxc,c)
        mrc[gm]=[minr,maxr,minc,maxc]

dt={}
def touch(a,b):
    am=min(a,b)
    b=a+b-am
    a=am
    if (a,b) in dt:
        return dt[a,b]
    else:
        dt[a,b]=((mrc[a][2]<=mrc[b][3]+2) and (mrc[b][2]<=mrc[a][3]+2)) or ((mrc[a][0]<=mrc[b][1]+2) and (mrc[b][0]<=mrc[a][1]+2))
        return dt[a,b]

toreach=rg[t[1][1]]
resg={}
toassign=dict(zip(dbg.keys(),[0]*len(dbg)))
minpay=None
if t[n][m]>0:
    gg=rg[t[n][m]]
    resg[gg]=0
    minpay=0
else:
    for i in range(n):
        if t[i][m]>0:
            resg[rg[t[i][m]]]=1
            minpay=1
        if t[i][m-1]>0:
            resg[rg[t[i][m-1]]]=1
            minpay=1
    for i in range(m):
        if t[n][i]>0:
            resg[rg[t[n][i]]]=1
            minpay=1
        if t[n-1][i]>0:
            resg[rg[t[n-1][i]]]=1
            minpay=1

nr=resg.keys()
for i in resg.keys():
    del toassign[i]
while toreach not in resg and len(nr)>0:
    nnr=[]
    for gm in nr:
        for i in toassign.keys():
            if touch(gm,i):
                nnr+=[i]
                resg[i]=resg[gm]+1
                del toassign[i]
    nr=nnr

if toreach not in resg:
    print -1
else:
    print resg[toreach]
#print res


n,m,k=[int(i) for i in raw_input().split(" ")]
t={}
nbg=0
dbg={}
rg={}
rrg={}

#for i in range(len(t)):
#    t[i]=[0]*(m+2)

def neighbourslit(r,c):
    res=[]
    for ii in [(r-1,c),(r+1,c),(r,c-1),(r,c+1)]:
        if ii in t:
            res+=[[ii[0],ii[1],rg[t[ii[0],ii[1]]]]]
    return res

for i in range(k):
    r,c=[int(j) for j in raw_input().split(" ")]
    nbs=neighbourslit(r,c)
    if len(nbs)==0:
        nbg+=1
        t[r,c]=nbg
        dbg[nbg]=[(r,c)]
        rg[nbg]=nbg
        rrg[nbg]=[nbg]
    else:
        myg=nbs[0][2]
        t[r,c]=myg
        dbg[myg]+=[(r,c)]
        for j in range(1,len(nbs)):
            oldg=rg[t[nbs[j][0],nbs[j][1]]]
            if myg!=oldg:
                rrg[myg]+=rrg[oldg]
                for g in rrg[oldg]:
                    rg[g]=myg
                del rrg[oldg]
                dbg[myg]+=dbg[oldg]
                del dbg[oldg]

#print "nb groupes : {} pour {} lampes".format(len(dbg),k)

#maxandmincolsofgroups
mrc={}
dr={}
dc={}
for gm in dbg.keys():
    minr=n+1
    maxr=0
    minc=m+1
    maxc=0
    for i in dbg[gm]:
        r=i[0]
        c=i[1]
        minr=min(minr,r)
        maxr=max(maxr,r)
        minc=min(minc,c)
        maxc=max(maxc,c)
    mrc[gm]=[minr,maxr,minc,maxc]
    for j in range(minr,maxr+1):
        if j not in dr:
            dr[j]=[]
        dr[j]+=[gm]
    for j in range(minc,maxc+1):
        if j not in dc:
            dc[j]=[]
        dc[j]+=[gm]

dt={}

def touch(a,b):
    am=min(a,b)
    b=a+b-am
    a=am
    if (a,b) in dt:
        return dt[a,b]
    else:
        dt[a,b]=((mrc[a][2]<=mrc[b][3]+2) and (mrc[b][2]<=mrc[a][3]+2)) or ((mrc[a][0]<=mrc[b][1]+2) and (mrc[b][0]<=mrc[a][1]+2))
        return dt[a,b]

toreach=rg[t[1,1]]
resg={}
toassign=dict(zip(dbg.keys(),[0]*len(dbg)))

def listgroupsinroworcols(rows="All",cols="All"):
    lights=[]
    for i in range(rows[0],rows[1]+1):
        if i in dr:
            lights+=dr[i]
    for i in range(cols[0],cols[1]+1):
        if i in dc:
            lights+=dc[i]
    return list(set(lights))
#    if rows!="All":
#        lights+=[i for i in t.keys() if i[0] in range(rows[0],rows[1]+1)]
#    if cols!="All":
#        lights+=[i for i in t.keys() if i[1] in range(cols[0],cols[1]+1)]
#    dr={}
#    for g in lights:
#        gg=rg[t[g]]
#        if gg not in dr:
#            dr[gg]=0
#    return dr.keys()

minpay=None
if (n,m) in  t:
    gg=rg[t[n,m]]
    resg[gg]=0
    minpay=0
else:
    for i in range(n):
        if (i,m) in t:
            resg[rg[t[i,m]]]=1
            minpay=1
        if (i,m-1) in t:
            resg[rg[t[i,m-1]]]=1
            minpay=1
    for i in range(m):
        if (n,i) in t:
            resg[rg[t[n,i]]]=1
            minpay=1
        if (n-1,i) in t:
            resg[rg[t[n-1,i]]]=1
            minpay=1

nr=resg.keys()
for i in resg.keys():
    del toassign[i]
while toreach not in resg and len(nr)>0:
    nnr=[]
    for gm in nr:
#        for i in toassign.keys():
#            if touch(gm,i):
#                nnr+=[i]
#                resg[i]=resg[gm]+1
#                del toassign[i]
        ng=listgroupsinroworcols((mrc[gm][0]-2,mrc[gm][1]+2),(mrc[gm][2]-2,mrc[gm][3]+2))
        nng=[i for i in ng if i in toassign]
        nnr+=nng
        for i in nng:
            nnr+=[i]
            resg[i]=resg[gm]+1
            del toassign[i]
    nr=nnr

if toreach not in resg:
    print -1
else:
    print resg[toreach]
#print res


import sys
from collections import defaultdict, deque

def readints():
    return map(int, sys.stdin.readline().split())

def main():
    adj = [(0, 1), (1, 0), (-1, 0), (0, -1)]
    inf = 10**9

    n, m, k = readints()
    xy_to_id = {}
    id_to_xy = {}
    d = defaultdict(lambda:inf)
    maxd_row = defaultdict(lambda: inf)
    maxd_col = defaultdict(lambda: inf)

    row_ids = defaultdict(set)
    col_ids = defaultdict(set)

    for i in xrange(k):
        x, y = readints()
        xy_to_id[(x, y)] = i
        row_ids[x].add(i)
        col_ids[y].add(i)
        id_to_xy[i] = (x, y)

    if (n, m) not in xy_to_id:
        xy_to_id[(n, m)] = k
        id_to_xy[k] = (n, m)
        row_ids[n].add(k)
        row_ids[m].add(k)

    q0 = deque()
    q1 = deque()
    q0.append((1, 1))
    q1.append((1, 1))
    d[0] = 0

    while q0 or q1:
        # print q0, q1
        # print d
        if q0:
            u = q0.popleft()
            ux, uy = u
            uid = xy_to_id[u]
            for dx, dy in adj:
                if 1 <= ux + dx <= n and 1 <= uy + dy <= m:
                    v = (ux + dx, uy + dy)
                    try:
                        vid = xy_to_id[v]
                        if vid < k and d[vid] > d[uid]:
                            d[vid] = d[uid]
                            q0.append(v)
                            q1.append(v)
                    except:
                        pass
        elif q1:
            u = q1.popleft()
            ux, uy = u
            uid = xy_to_id[u]

            for rowdelta in (-2, -1, 0, 1, 2):
                new_row = ux + rowdelta
                if 1 <= new_row <= n and maxd_row[new_row] > d[uid] + 1:
                    maxd_row[new_row] = 0
                    for vid in row_ids[new_row]:
                        # print "ROW", rowdelta, new_row, row_ids[new_row]
                        if (vid < k or rowdelta in (-1, 0, 1)) and d[vid] > d[uid] + 1:
                            d[vid] = d[uid] + 1
                            v = id_to_xy[vid]
                            q0.append(v)
                            q1.append(v)
                        maxd_row[new_row] = max(maxd_row[new_row], d[vid])

            for coldelta in (-2, -1, 0, 1, 2):
                new_col = ux + coldelta
                if 1 <= new_col <= m and maxd_col[new_col] > d[uid] + 1:
                    maxd_col[new_col] = 0
                    for vid in col_ids[new_col]:
                        if (vid < k or coldelta in (-1, 0, 1)) and d[vid] > d[uid] + 1:
                            d[vid] = d[uid] + 1
                            v = id_to_xy[vid]
                            q0.append(v)
                            q1.append(v)
                        maxd_col[new_col] = max(maxd_col[new_col], d[vid])
    res = d[xy_to_id[(n, m)]]
    if res == inf:
        print -1
    else:
        print res

if __name__ == "__main__":
    main()


import sys
from collections import defaultdict, deque

def readints():
    return map(int, sys.stdin.readline().split())

def main():
    adj = [(0, 1), (1, 0), (-1, 0), (0, -1)]
    inf = 10**9

    n, m, k = readints()
    xy_to_id = {}
    id_to_xy = {}
    d = defaultdict(lambda:inf)
    maxd_row = defaultdict(lambda: inf)
    maxd_col = defaultdict(lambda: inf)

    row_ids = defaultdict(set)
    col_ids = defaultdict(set)

    for i in xrange(k):
        x, y = readints()
        xy_to_id[(x, y)] = i
        row_ids[x].add(i)
        col_ids[y].add(i)
        id_to_xy[i] = (x, y)

    if (n, m) not in xy_to_id:
        xy_to_id[(n, m)] = k
        id_to_xy[k] = (n, m)
        row_ids[n].add(k)
        row_ids[m].add(k)

    q0 = deque()
    q1 = deque()
    q0.append((1, 1))
    q1.append((1, 1))
    d[0] = 0

    while q0 or q1:
        # print q0, q1
        # print d
        if q0:
            u = q0.popleft()
            ux, uy = u
            uid = xy_to_id[u]
            for dx, dy in adj:
                if 1 <= ux + dx <= n and 1 <= uy + dy <= m:
                    v = (ux + dx, uy + dy)
                    try:
                        vid = xy_to_id[v]
                        if d[vid] > d[uid]:
                            d[vid] = d[uid]
                            q0.append(v)
                            q1.append(v)
                    except:
                        pass
        elif q1:
            u = q1.popleft()
            ux, uy = u
            uid = xy_to_id[u]

            for rowdelta in (-2, -1, 0, 1, 2):
                new_row = ux + rowdelta
                if 1 <= new_row <= n and maxd_row[new_row] > d[uid] + 1:
                    maxd_row[new_row] = 0
                    for vid in row_ids[new_row]:
                        # print "ROW", rowdelta, new_row, row_ids[new_row]
                        if (vid < k or rowdelta in (-1, 0, 1)) and d[vid] > d[uid] + 1:
                            d[vid] = d[uid] + 1
                            v = id_to_xy[vid]
                            q0.append(v)
                            q1.append(v)
                        maxd_row[new_row] = max(maxd_row[new_row], d[vid])

            for coldelta in (-2, -1, 0, 1, 2):
                new_col = ux + coldelta
                if 1 <= new_col <= m and maxd_col[new_col] > d[uid] + 1:
                    maxd_col[new_col] = 0
                    for vid in col_ids[new_col]:
                        if (vid < k or coldelta in (-1, 0, 1)) and d[vid] > d[uid] + 1:
                            d[vid] = d[uid] + 1
                            v = id_to_xy[vid]
                            q0.append(v)
                            q1.append(v)
                        maxd_col[new_col] = max(maxd_col[new_col], d[vid])
    res = d[xy_to_id[(n, m)]]
    if res == inf:
        print -1
    else:
        print res

if __name__ == "__main__":
    main()


import sys
from collections import defaultdict, deque

def readints():
    return map(int, sys.stdin.readline().split())

def main():
    adj = [(0, 1), (1, 0), (-1, 0), (0, -1)]
    inf = 10**9

    n, m, k = readints()
    xy_to_id = {}
    id_to_xy = {}
    d = defaultdict(lambda:inf)
    maxd_row = defaultdict(lambda: inf)
    maxd_col = defaultdict(lambda: inf)

    row_ids = defaultdict(set)
    col_ids = defaultdict(set)

    for i in xrange(k):
        x, y = readints()
        xy_to_id[(x, y)] = i
        row_ids[x].add(i)
        col_ids[y].add(i)
        id_to_xy[i] = (x, y)

    if (n, m) not in xy_to_id:
        xy_to_id[(n, m)] = k
        id_to_xy[k] = (n, m)
        row_ids[n].add(k)
        col_ids[m].add(k)

    q0 = deque()
    q1 = deque()
    q0.append((1, 1))
    q1.append((1, 1))
    d[0] = 0

    while q0 or q1:
        #  print q0, q1
        # print d
        if q0:
            u = q0.popleft()
            ux, uy = u
            uid = xy_to_id[u]
            for dx, dy in adj:
                if 1 <= ux + dx <= n and 1 <= uy + dy <= m:
                    v = (ux + dx, uy + dy)
                    try:
                        vid = xy_to_id[v]
                        if vid < k and d[vid] > d[uid]:
                            d[vid] = d[uid]
                            q0.append(v)
                            q1.append(v)
                    except:
                        pass
        elif q1:
            u = q1.popleft()
            ux, uy = u
            uid = xy_to_id[u]

            for rowdelta in (-2, -1, 0, 1, 2):
                new_row = ux + rowdelta
                if 1 <= new_row <= n and maxd_row[new_row] > d[uid] + 1:
                    maxd_row[new_row] = 0
                    for vid in row_ids[new_row]:
                        # print "ROW", rowdelta, new_row, row_ids[new_row]
                        if (vid < k or rowdelta in (-1, 0, 1)) and d[vid] > d[uid] + 1:
                            d[vid] = d[uid] + 1
                            v = id_to_xy[vid]
                            q0.append(v)
                            q1.append(v)
                        maxd_row[new_row] = max(maxd_row[new_row], d[vid])

            for coldelta in (-2, -1, 0, 1, 2):
                new_col = uy + coldelta
                if 1 <= new_col <= m and maxd_col[new_col] > d[uid] + 1:
                    # print "COL", coldelta, new_col, col_ids[new_col]
                    maxd_col[new_col] = 0
                    for vid in col_ids[new_col]:
                        if (vid < k or coldelta in (-1, 0, 1)) and d[vid] > d[uid] + 1:
                            d[vid] = d[uid] + 1
                            v = id_to_xy[vid]
                            q0.append(v)
                            q1.append(v)
                        maxd_col[new_col] = max(maxd_col[new_col], d[vid])
    res = d[xy_to_id[(n, m)]]
    if res == inf:
        print -1
    else:
        print res

if __name__ == "__main__":
    main()