// Slower C++ solution:
#include<bits/stdc++.h>

using namespace std;

using Int = long long;

template<typename T1,typename T2> inline void chmin(T1 &a,T2 b){if(a>b) a=b;}

template<typename T1,typename T2> inline void chmax(T1 &a,T2 b){if(a<b) a=b;}



template<typename T,T MOD = 1000000007>

struct Mint{

  T v;

  Mint():v(0){}

  Mint(signed v):v(v){}

  Mint(long long t){v=t%MOD;if(v<0) v+=MOD;}



  Mint pow(long long k){

    Mint res(1),tmp(v);

    while(k){

      if(k&1) res*=tmp;

      tmp*=tmp;

      k>>=1;

    }

    return res;

  }

  

  Mint inv(){return pow(MOD-2);}

  

  Mint& operator+=(Mint a){v+=a.v;if(v>=MOD)v-=MOD;return *this;}

  Mint& operator-=(Mint a){v+=MOD-a.v;if(v>=MOD)v-=MOD;return *this;}

  Mint& operator*=(Mint a){v=1LL*v*a.v%MOD;return *this;}

  Mint& operator/=(Mint a){return (*this)*=a.inv();}

  

  Mint operator+(Mint a) const{return Mint(v)+=a;};

  Mint operator-(Mint a) const{return Mint(v)-=a;};

  Mint operator*(Mint a) const{return Mint(v)*=a;};

  Mint operator/(Mint a) const{return Mint(v)/=a;};



  Mint operator-(){return v?MOD-v:v;}



  bool operator==(const Mint a)const{return v==a.v;}

  bool operator!=(const Mint a)const{return v!=a.v;}

  bool operator <(const Mint a)const{return v <a.v;}

  

};



//INSERT ABOVE HERE

const int MAX = 303;

using M = Mint<int>;

M dp[MAX][MAX*2];

int used[MAX*2];

int side[MAX*2];

signed main(){

  int n;

  cin>>n;

  vector<int> a(n*2);

  for(int i=0;i<n*2;i++) cin>>a[i];

  

  memset(used,0,sizeof(used));

  for(int i=0;i<n*2;i++)

    if(~a[i]) used[a[i]]=1;



  int cnt=0;  

  memset(side,0,sizeof(side));

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

    if(a[i*2]<0&&a[i*2+1]<0){

      cnt++;

      continue;

    }

    if(a[i*2]>0&&a[i*2+1]>0) continue;

    if(a[i*2]>0) side[a[i*2]]=1;

    if(a[i*2+1]>0) side[a[i*2+1]]=1;

  }

  

  for(int j=0;j<MAX;j++)

    for(int k=0;k<MAX*2;k++)

      dp[j][k]=0;



  dp[0][0]=1;

  

  int num=0,laz=0;

  for(int i=n*2;i>=1;i--){

    if(used[i]&&!side[i]) continue;

    

    if(used[i]){

      assert(side[i]);

      for(int j=n;j>=0;j--)

        for(int k=n*2;k>=0;k--)

          if(j*2+k+1<=laz) dp[j][k+1]+=dp[j][k];

      num++;

      continue;

    }

    

    if(!used[i]){      

      for(int j=n;j>=0;j--){

        for(int k=n;k>=0;k--){         

          if(j*2+k+1<=laz&&j+1<=cnt) dp[j+1][k]+=dp[j][k]*M(cnt-j);

          if(k+1<=num) dp[j][k+1]+=dp[j][k]*M(num-k);          

        }

      }

      laz++;

      continue;

    }

  }

  

  M ans=dp[cnt][num];

  cout<<ans.v<<endl;

  return 0;

}


// Faster C++ solution for the same problem (measured speedup: 1.2844471457621298x):
#include<bits/stdc++.h>

using namespace std;

using Int = long long;

template<typename T1,typename T2> inline void chmin(T1 &a,T2 b){if(a>b) a=b;}

template<typename T1,typename T2> inline void chmax(T1 &a,T2 b){if(a<b) a=b;}



template<typename T,T MOD = 1000000007>

struct Mint{

  T v;

  Mint():v(0){}

  Mint(signed v):v(v){}

  Mint(long long t){v=t%MOD;if(v<0) v+=MOD;}



  Mint pow(long long k){

    Mint res(1),tmp(v);

    while(k){

      if(k&1) res*=tmp;

      tmp*=tmp;

      k>>=1;

    }

    return res;

  }

  

  Mint inv(){return pow(MOD-2);}

  

  Mint& operator+=(Mint a){v+=a.v;if(v>=MOD)v-=MOD;return *this;}

  Mint& operator-=(Mint a){v+=MOD-a.v;if(v>=MOD)v-=MOD;return *this;}

  Mint& operator*=(Mint a){v=1LL*v*a.v%MOD;return *this;}

  Mint& operator/=(Mint a){return (*this)*=a.inv();}

  

  Mint operator+(Mint a) const{return Mint(v)+=a;};

  Mint operator-(Mint a) const{return Mint(v)-=a;};

  Mint operator*(Mint a) const{return Mint(v)*=a;};

  Mint operator/(Mint a) const{return Mint(v)/=a;};



  Mint operator-(){return v?MOD-v:v;}



  bool operator==(const Mint a)const{return v==a.v;}

  bool operator!=(const Mint a)const{return v!=a.v;}

  bool operator <(const Mint a)const{return v <a.v;}

  

};



//INSERT ABOVE HERE

const int MAX = 303;

using M = Mint<int>;

M dp[MAX][MAX];

int used[MAX*2];

int side[MAX*2];

signed main(){

  int n;

  cin>>n;

  vector<int> a(n*2);

  for(int i=0;i<n*2;i++) cin>>a[i];

  

  memset(used,0,sizeof(used));

  for(int i=0;i<n*2;i++)

    if(~a[i]) used[a[i]]=1;



  int cnt=0;  

  memset(side,0,sizeof(side));

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

    if(a[i*2]<0&&a[i*2+1]<0){

      cnt++;

      continue;

    }

    if(a[i*2]>0&&a[i*2+1]>0) continue;

    if(a[i*2]>0) side[a[i*2]]=1;

    if(a[i*2+1]>0) side[a[i*2+1]]=1;

  }

  

  for(int j=0;j<MAX;j++)

    for(int k=0;k<MAX;k++)

      dp[j][k]=0;



  dp[0][0]=1;

  

  int num=0,laz=0;

  for(int i=n*2;i>=1;i--){

    if(used[i]&&!side[i]) continue;

    

    if(used[i]){

      assert(side[i]);

      for(int j=n;j>=0;j--)

        for(int k=n;k>=0;k--)

          if(j*2+k+1<=laz) dp[j][k+1]+=dp[j][k];

      num++;

      continue;

    }

    

    if(!used[i]){      

      for(int j=n;j>=0;j--){

        for(int k=n;k>=0;k--){         

          if(j*2+k+1<=laz&&j+1<=cnt) dp[j+1][k]+=dp[j][k]*M(cnt-j);

          if(k+1<=num) dp[j][k+1]+=dp[j][k]*M(num-k);          

        }

      }

      laz++;

      continue;

    }

  }

  

  M ans=dp[cnt][num];

  cout<<ans.v<<endl;

  return 0;

}