//WA哭了 特么自己把n,m写反了! //简单dancing link优化! #include <iostream> #include <queue> #include <stack> #include <string> #include <map> #include <vector> #include <cstring> #include <cstdio> #include <cmath> #include <algorithm> using namespace std; const int MAX=30*30*500+5+500,INF=1<<30; const int h=0; int cnt; int L[MAX],R[MAX],U[MAX],D[MAX], Col[MAX], S[MAX]; int deep,ans; inline void init(int m){ for(int i=1;i<=m;i++){ L[i]=i-1; R[i]=i+1; U[i]=i; D[i]=i; Col[i]=i; S[i]=0; } cnt=m; L[h]=m; R[h]=1; R[m]=h; return ; } inline void remove(const int &c){ L[R[c]]=L[c]; R[L[c]]=R[c]; for(int i=D[c];i!=c;i=D[i]){ for(int j=R[i];j!=i;j=R[j]){ U[D[j]]=U[j]; D[U[j]]=D[j]; --S[Col[j]]; } } return ; } inline void resume(const int &c){ for(int i=U[c];i!=c;i=U[i]){ for(int j=L[i];j!=i;j=L[j]){ U[D[j]]=j; D[U[j]]=j; ++S[Col[j]]; } } L[R[c]]=c; R[L[c]]=c; return ; } void dfs(){ if(R[h]==h){ ans=min(ans,deep); return ; } int minVal=INF,idx=R[h]; for(int i=R[h];i!=h;i=R[i]){ if(S[i]<minVal){ minVal=S[i]; idx=i; if(minVal==1) break; } } remove(idx); for(int i=D[idx];i!=idx;i=D[i]){ for(int j=R[i];j!=i;j=R[j]) remove(Col[j]); ++deep; dfs(); --deep; for(int j=L[i];j!=i;j=L[j]) resume(Col[j]); } resume(idx); return ; } int main() { #ifndef ONLINE_JUDGE freopen("i.txt", "r", stdin); #endif bool flag; int T,n,m,p, x1,y1,x2,y2, l,idx, ColLast,pre; scanf("%d",&T); while(T--){ scanf("%d%d%d",&m,&n,&p); l=m; m=n*m; init(m); for(int i=1;i<=p;i++){ scanf("%d%d%d%d",&x1,&y1,&x2,&y2); pre=0; for(int r=y1;r<y2;r++){ for(int c=x1;c<x2;c++){ idx=r*l+c+1; ++S[idx]; ColLast=U[idx]; U[++cnt]=ColLast; D[cnt]=idx; D[U[cnt]]=cnt; U[D[cnt]]=cnt; L[cnt]=pre?pre:cnt; R[cnt]=pre?R[pre]:cnt; L[R[cnt]]=cnt; R[L[cnt]]=cnt; Col[cnt]=idx; pre=cnt; } } } flag=false; for(int i=1;i<=m;i++){ if(S[i]==0){ flag=true; break; } } if(flag){ printf("-1/n"); continue; } ans=INF; deep=0; dfs(); //cout<<deep<<endl; //cout<<"CNT:"<<cnt<<endl; printf("%d/n",ans==INF?-1:ans); } return 0; }