Problem:
Score : 1500 points

Problem Statement

There is an undirected connected graph with N vertices numbered 1 through N.
The lengths of all edges in this graph are 1.
It is known that for each i (1≦i≦N), the distance between vertex 1 and vertex i is A_i, and the distance between vertex 2 and vertex i is B_i.
Determine whether there exists such a graph.
If it exists, find the minimum possible number of edges in it.

Constraints

2≦N≦10^5

0≦A_i,B_i≦N-1

Input

The input is given from Standard Input in the following format:

N
A_1 B_1
A_2 B_2
:
A_N B_N

Output

If there exists a graph satisfying the conditions, print the minimum possible number of edges in such a graph. Otherwise, print -1.

Sample Input 1

4
0 1
1 0
1 1
2 1

Sample Output 1

4

The figure below shows two possible graphs. The graph on the right has fewer edges.

Sample Input 2

3
0 1
1 0
2 2

Sample Output 2

-1

Such a graph does not exist.

Solution in C++14 (GCC 5.4.1) (judge verdict: Accepted)

#include<bits/stdc++.h>
using namespace std;
const int maxn=100005;
struct SHIT
{
    int one,two;
    bool operator<(const SHIT  &b)const {
        if(this->one!=b.one) return (this->one<b.one);
        return (this->two<b.two);
    }
}shit[maxn];
bool cmp(SHIT a,SHIT b)
{
    if(a.one+a.two!=b.one+b.two)
        return a.one+a.two<b.one+b.two;
    return a.one<b.one;
}
map<SHIT,bool>mp;
int main()
{
    int n;
    mp.clear();
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
    {
        scanf("%d%d",&shit[i].one,&shit[i].two);
        mp[shit[i]]=1;
    }
    if(!(shit[1].one==shit[2].two&&shit[1].two==shit[2].one&&shit[1].one==0&&shit[1].two!=0)){
        puts("-1");
        return 0;
    }
    int mn=shit[1].two;
    int ans=2*n-2;
    for(int i=3;i<=n;i++)
    {
        if(shit[i].one==0||shit[i].two==0||shit[i].one+shit[i].two<mn){
            puts("-1");
            return 0;
        }
    }
    sort(shit+1,shit+n+1,cmp);
    for(int i=1,j;i<=n;i=j)
    {
        j=i+1;
        while(j<=n&&shit[j].one+shit[j].two==shit[i].one+shit[i].two)
            j++;
        for(int k=i;k<j;k++)
            mp[shit[k]]=1;
        int last=0,left=0;
        for(int k=i,tk;k<j;k=tk)
        {
            tk=k+1;
            while(tk<j&&shit[tk].one==shit[k].one){
                tk++;
            }
            int now=tk-k;
            bool one=0,two=0;
            SHIT tmp1,tmp2;
            tmp1.one=shit[k].one-1;
            tmp1.two=shit[k].two-1;
            if(mp.count(tmp1)){
                one=1;two=1;
            }


            tmp1.one=shit[k].one-1;
            tmp1.two=shit[k].two+1;
            tmp2.one=shit[k].one+1;
            tmp2.two=shit[k].two-1;



            one=one|mp.count(tmp1);
            two=two|mp.count(tmp2);

            tmp1.two--;
            tmp2.one--;
            one=one|mp.count(tmp1);
            two=two|mp.count(tmp2);

            if(shit[k].one==0)one=1;
            if(shit[k].two==0) two=1;
            if(one==0||two==0){
                puts("-1");
                return 0;
            }
            int del=0;
            if(last+1==shit[k].one){
                del=min(now,left);
                ans-=del;
            }
            tmp1.two--;
            if(mp.count(tmp1)){
                ans-=now-del;
                now=del;
            }
            last=shit[k].one;
            left=now;
        }
    }
    printf("%d\n",ans);
    return 0;
}