参考https://blog.csdn.net/qq_35479641/article/details/51887172该题的DLX模板
#include <iostream>
#include <cstdio>
using namespace std;
const int maxnode=100010;//最大节点数
const int maxm=1010;//最大列数
const int maxn=1010;//最大行数
const int inf = 0x3f3f3f3f;
class dlx {
public:
int n,m,size;
int R[maxnode],L[maxnode],U[maxnode],D[maxnode],col[maxnode],H[maxn],row[maxnode],S[maxm];
//表示最后选中的行的数量,ans记录答案
int res,ans[maxn];
void init(int x,int y) {
n=x;
m=y;
res = inf;
int i;
for(i=0; i<=m; i++) {
S[i]=0;
U[i]=i;
D[i]=i;
L[i]=i-1;
R[i]=i+1;
}
L[0]=m;
R[m]=0;
size=m;
for(i=0; i<=n; i++) {
H[i]=-1;
}
}
void link(int r,int c) {
size++;
col[size]=c;
row[size]=r;
S[col[size]]++;
U[size]=c;
D[size]=D[c];
U[D[c]]=size;
D[c]=size;
if(H[r]<0) {
H[r]=L[size]=R[size]=size;
}
else {
R[size]=R[H[r]];
L[size]=H[r];
L[R[H[r]]]=size;
R[H[r]]=size;
}
}
void remove(int c) {
R[L[c]]=R[c];
L[R[c]]=L[c];
int x,y;
for(x=D[c]; x!=c; x=D[x]) {
for(y=R[x]; y!=x; y=R[y]) {
D[U[y]]=D[y];
U[D[y]]=U[y];
S[col[y]]--;
}
}
}
void resume(int c) {
int i,j;
for(i=U[c]; i!=c; i=U[i]) {
for(j=L[i]; j!=i; j=L[j]) {
U[D[j]]=j;
D[U[j]]=j;
S[col[j]]++;
}
}
L[R[c]]=R[L[c]]=c;
}
void dance(int cnt) {
//当原点的右边结点是自己时,所有的已经全部删除完毕,符合条件
if(R[0]==0) {
res=min(res, cnt);
return;
}
int cur;
cur=R[0];
for(int i=cur; i!=0; i=R[i]) {
if(S[cur]>S[i]) {
cur=i;
}
}
remove(cur);
int i,j;
for(i=D[cur]; i!=cur; i=D[i]) {
for(j=R[i]; j!=i; j=R[j]) {
remove(col[j]);
}
dance(cnt+1);
for(j=L[i]; j!=i; j=L[j]) {
resume(col[j]);
}
}
resume(cur);
return;
}
};
dlx test;
int main() {
int nn,mm, k, T;
scanf("%d", &T);
while(T--) {
scanf("%d%d%d", &nn, &mm, &k);
test.init(k,nn*mm);
int cn=0, j, x1, y1, x2, y2;
for(int i=1; i<=k; i++) {
scanf("%d%d%d%d", &x1, &y1, &x2, &y2);
for(int j=x1; j<x2; j++) {
for(int k=y1+1; k<=y2; k++)
test.link(i, j*mm+k);
}
}
test.dance(0);
printf("%d", test.res == inf ? -1 : test.res);
printf("\n");
}
return 0;
}