#region ZIPPER
using System;
using System.Collections.Generic;
using System.Collections;
using System.Linq;
using System.Text;
using sc = Scanner;
//using Geometry;
//using gl = Geometry.GeometryLibrary;
class Program
{
static void Main(string[] args)
{
Solver solver = new Solver();
solver.Solve();
#if DEBUG
System.Console.WriteLine("続行するには何かキーを押してください...");
System.Console.ReadKey();
#endif
}
}
///
/// 標準入力読み取り支援,自作(某最速の人を参考)
///
#endregion ZIPPER
public class Solver
{
#region IGNORE_ME
public Solver()
{
//こんすとらくたん きにしなくてよろしい
}
#endregion IGNORE_ME
public int MOD = 1000000007;
public void Solve()
{
int n = sc.NextInt();
int[][] ab = new int[n][];
int maxLine = 0;
int answer = 0;
for (int i = 0; i < n; i++)
{
ab[i] = sc.NextIntArray();
}
int[] k = new int[n];
for (int i = 0; i < n; i++)
{
k[i] = ab[i][0] + 4 * ab[i][1];
if (k[i] > maxLine)
{
maxLine = k[i];
}
}
int oddOrEven = k[0] % 2;
for (int i = 0; i < k.Length; i++)
{
if (k[i] % 2 != oddOrEven)
{
Console.WriteLine("-1");
return;
}
}
for (int i = 0; i < n; i++)
{
answer += (maxLine - k[i])/2;
}
Console.WriteLine(answer);
/* nimonme yo
int h = sc.NextInt();
int w = sc.NextInt();
CharInterpreter.AddCorrespondence('#', 1);
CharInterpreter.AddCorrespondence('.', 0);*/
#if DEBUG
Console.WriteLine("");//local check
#endif
}
}
///
/// セグメント木
///
/// データ型
public class SegmentTree
{
///
/// 格納可能な数
///
public int Length { get; private set; }
///
/// 計算上無効なノードを規定する 最小値→int.MaxValue 参照型→null など
///
public T InvalidValue { get; private set; }
///
/// 2つの区間を結合するときの処理方法を動的に決定する
/// このとき a
///
///
///
///
public delegate T Marging(T a, T b);
///
/// 要素が計算上で無効な要素出ることを調べる方法を動的に決定する.
///
///
///
///
public delegate bool ComparisonInvalidValue(T a);
///
/// インデクサで配列っぽく葉の要素の更新が処理できる! It's cool...
///
///
///
public T this[int index]
{
get
{
return Data[Length / 2 - 1 + index];
}
set
{
Update(index, value);
}
}
///
/// 集合,あるいは要素の2つ,A,BからA∩Bを求める.
/// Tが参照型のとき,新しくインスタンスを生成しないとバグることに注意.
///
public Marging Marge { get; private set; }
///
/// 計算に含めてはいけないアイテムかどうか
///
public ComparisonInvalidValue IsInvalidItem { get; private set; }
private T[] Data;
///
/// コンストラクタ
///
/// 最低限確保したい領域,内部ではlength≦2^nを満たす最小の2^n個分確保する.利用上の影響はない
/// 使わない領域を弾くための無効値
public SegmentTree(int length, T invalidValue, Marging marge, ComparisonInvalidValue isInvalidValue)
{
this.Marge = marge;
this.InvalidValue = invalidValue;
this.IsInvalidItem = isInvalidValue;
//配列を2^n分確保する lengthより大きめ
for (int i = 1; ; i *= 2)
if (i > length)
{
Data = new T[2 * i];
break;
}
for (int i = 0; i < Data.Length; i++)
{
Data[i] = invalidValue;
}
Length = Data.Length / 2;
}
///
/// 更新する
///
///
///
public void Update(int k, T elem)
{
k += Length - 1;
Data[k] = elem;
while (k > 0)
{
k = (k - 1) / 2;
Data[k] = Marge(Data[k * 2 + 1], Data[k * 2 + 2]);
}
}
///
/// 区間に対する問い合わせをlog n で処理する
/// 求める区間の値は[start,end-1),言い換えるとstartからend-1までの区間に注目する.(start=endとかするとバグる)
///
/// 配列の始点 0から
/// 配列の終点 n-1___ まで
///
public T RangeQuery(int start, int end)
{
return RecursionQuery(start, end, 0, 0, Length);
}
private T RecursionQuery(int start, int end, int k, int l, int r)
{
if (r <= start || end <= l) return InvalidValue; //区間にかすりすらしない
if (start <= l && r <= end) return Data[k]; //区間の中にすっぽり入る
else //交差してるので分割して調べる
{
return Marge(
RecursionQuery(start, end, k * 2 + 1, l, (l + r) / 2)
, RecursionQuery(start, end, k * 2 + 2, (l + r) / 2, r)
);
}
}
}
public static class Scanner
{
public static string NextString()
{
string tmp = "";
while (true)
{
int readData;
string data;
readData = Console.Read();
if (readData == -1) //EOF
{
break;
}
data = char.ConvertFromUtf32(readData);
if (data == " " || data == "\n")
{
break;
}
tmp += data;
}
return tmp;
}
public static int NextInt()
{
string tmp = "";
while (true)
{
int readData;
string data;
readData = Console.Read();
if (readData == -1) //EOF
{
break;
}
data = char.ConvertFromUtf32(readData);
if (data == " " || data == "\n")
{
break;
}
tmp += data;
}
return int.Parse(tmp);
}
public static long NextLong()
{
string tmp = "";
while (true)
{
int readData;
string data;
readData = Console.Read();
if (readData == -1) //EOF
{
break;
}
data = char.ConvertFromUtf32(readData);
if (data == " " || data == "\n")
{
break;
}
tmp += data;
}
return long.Parse(tmp);
}
public static double NextDouble()
{
string tmp = "";
while (true)
{
int readData;
string data;
readData = Console.Read();
if (readData == -1) //EOF
{
break;
}
data = char.ConvertFromUtf32(readData);
if (data == " " || data == "\n")
{
break;
}
tmp += data;
}
return double.Parse(tmp);
}
public static string[] NextStrArray()
{
return Console.ReadLine().Split(' ');
}
public static int[] NextIntArray()
{
string[] s = NextStrArray();
int[] a = new int[s.Length];
for (int i = 0; i < a.Length; i++)
{
a[i] = int.Parse(s[i]);
}
return a;
}
public static long[] NextLongArray()
{
string[] s = NextStrArray();
long[] a = new long[s.Length];
for (int i = 0; i < a.Length; i++)
{
a[i] = long.Parse(s[i]);
}
return a;
}
public static double[] NextDoubleArray()
{
string[] s = NextStrArray();
double[] a = new double[s.Length];
for (int i = 0; i < a.Length; i++)
{
a[i] = double.Parse(s[i]);
}
return a;
}
}
///
/// 二次元グリッドなどの文字列で与えられたマップなどで、
/// 手軽にデータ変換を適用するためのクラス
///
public static class CharInterpreter
{
///
/// 変換用辞書
///
private static Dictionary MapToInt = new Dictionary();
///
/// 変換法則を追加する
///
/// char文字
/// 対応する整数値
public static void AddCorrespondence(char c,int i)
{
MapToInt.Add(c,i);
}
///
/// 文字列に対して、対応付けされた
/// 例外処理をしていないので注意
///
/// 対応対応がなかった場合はバグる;;
public static int Inquiry(char c)
{
int ret = 0;
MapToInt.TryGetValue(c, out ret);
return ret;
}
///
/// 指定された変換法則の元でint[,]の二次元平面を生成する
/// 対応関係がない場合の例外処理をしていないので注意
///
/// 配列の各文字列の長さが全て同じでないとうまく作動しないので注意
/// int[ field.length , field[0].length]型の配列
public static int[,] GenerateSquareField(string[] field)
{
int[,] ret = new int[field.Length, field[0].Length];
for (int i = 0; i < field.Length; i++)
{
for (int j = 0; j < field[0].Length; j++)
{
MapToInt.TryGetValue(field[i][j], out ret[i, j]);
}
}
return ret;
}
}
/*
C 40点
public void Solve()
{
int n = sc.NextInt();
string s = Console.ReadLine();
int[] c = sc.NextIntArray();
int[] dp = new int[n+1];
for (int i = 1; i < dp.Length; i++)
{
dp[i] = int.MaxValue;
}
for (int i = 0; i < dp.Length; i++)
{
for (int j = i; j = s.Length)
{
return false;
}
#if DEBUG
Console.WriteLine(" {0};{1},",start,end);
#endif
for (int i = 0; start + i < end - i; i++)
{
if (!s[start+i].Equals(s[end - i]))
{
#if DEBUG
Console.WriteLine("out" + s[start + i] + " " + s[end - i]);
#endif
return false;
}
}
#if DEBUG
Console.WriteLine("OK\n");
#endif
return true;
}
*/