说实话这么奇怪十字的链表结构还能在里面删来恢复,按各种顺序和套路以致把时间复杂度减下来,果然是Knuth !
主要是计算最小列从n*m变成了m了,这里m是指下面代码的mm
#include <cstdio>
#include <memory>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <vector>
#include <cassert>
#include <string>
#include <ctime>
#include <map>
#include <queue>
#include <algorithm>
#include <iostream>
#include <cassert>
#include <iomanip>
#include <set>
#include <iterator>
using namespace std;
#define REP(i,n) for(int i=0;i<n;i++)
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define req(i,a,b) for(int i=a;i>=b;i--)
#define rp(i,a) for(int i=head[a];i+1;i=edge[i].next)
#define cl(a,b) memset(a,b,sizeof a);
#define ll long long
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define mod 10007
const int inf = ~0u >> 2;
const ll INF = (1LL << 62) - 1;
double eps = 1e-12;
const int N = 505 + 5;
const int M = 35*35;
int s[N];
int n, m, k;
//int a[M][M];
int b[M*N+M];
class DLX {
private:
const static int maxn = M*N+M;
public:
int l[maxn], r[maxn], u[maxn], d[maxn], s[M];
int row[maxn],col[maxn],head[N];
int sz = 0;
void init(int n,int mm) {
cnt = 0;
ans = inf;
level = 0;
sz = 0;
for (int j = 0; j <= mm; j++)
{
row[j] = 0;
col[j] = j;
s[j] = 0;
l[j] = j - 1;
r[j] = j + 1;
u[j] = d[j] = j;
sz++;
}
sz--;
l[0] = mm;
r[mm] = 0;
for (int i = 1; i <= n; i++)
head[i] = -1;
}
void remove(int y) {//y is column index
r[l[y]] = r[y];
l[r[y]] = l[y];
for (int i = d[y]; i != y; i = d[i]) {
for (int j = r[i]; j != i; j = r[j]) {
d[u[j]] = d[j];
u[d[j]] = u[j];
s[col[j]]--;
}
}
}
void resume(int y) {//y is column index
for (int i = u[y]; i != y; i = u[i]) {
for (int j = l[i]; j != i; j = l[j]) {
d[u[j]] = j;
u[d[j]] = j;
s[col[j]]++;
}
}
l[r[y]] = y;
r[l[y]] = y;
}
void link(int rowIndex, int colIndex) {
col[++sz] = colIndex;
s[colIndex]++;
d[sz] = d[colIndex];
u[sz] = colIndex;
u[d[sz]] = sz;
d[u[sz]] = sz;
if (head[rowIndex] == -1)
{
l[sz] = r[sz] = sz;
head[rowIndex] = sz;
}
else {
l[sz] = head[rowIndex];
r[sz] = r[head[rowIndex]];
l[r[sz]] = sz;
r[l[sz]] = sz;
}
}
bool dance() {
if (r[0] == 0) {
return true;
}
int minum = r[0];
for (int i = r[0]; i != 0; i = r[i]) {
if (s[i] < s[minum])
minum = i;
}
if (s[minum] == 0) {
return false;
}
level++;
if (level >= ans)
{
level--;
return false;
}
remove(minum);
for (int i = d[minum]; i != minum; i = d[i]) {
for (int j = r[i]; j != i; j = r[j]) {
remove(col[j]);
}
bool flag = dance();
for (int j = l[i]; j != i; j = l[j]) {
resume(col[j]);
}
if (flag||level>=ans) {
cnt++;
ans = min(ans, level);
break;
}
}
resume(minum);
level--;
return false;
}
int getAns() {
return ans;
}
private:
int cnt = 0;
int ans = inf;
int level = 0;
}dlx;
int main() {
int t;
//std::ios::sync_with_stdio(false);
scanf("%d", &t);
while (t--) {
scanf("%d%d%d", &n, &m, &k);
int mm = n*m;
dlx.init(k,mm);
for (int p = 1; p <= k; p++) {
int x, y, xx, yy;
scanf("%d%d%d%d", &x, &y, &xx, &yy);
for (int i = x + 1; i <= xx; i++)
{
for (int j = y + 1; j <= yy; j++) {
dlx.link(p, (i - 1)*m + j);
}
}
}
dlx.dance();
printf("%d
", dlx.getAns()==inf?-1:dlx.getAns());
}
return 0;
}