【题意】:给出一个n*m的矩阵,只有0和1,问能否从这个矩阵中选取x行使得每列有且仅有一个1.

【题解】:精确覆盖,DLX最基础的题目,十字链表确实足够强大。留下DLX模板~

【代码】:
  1 #include "iostream"
  2 #include "cstdio"
  3 #include "cstring"
  4 #include "algorithm"
  5 #include "vector"
  6 #include "queue"
  7 #include "cmath"
  8 #include "string"
  9 #include "cctype"
 10 #include "map"
 11 #include "iomanip"
 12 #include "set"
 13 #include "utility"
 14 using namespace std;
 15 typedef pair<intint> pii;
 16 #define pb push_back
 17 #define mp make_pair
 18 #define fi first
 19 #define se second
 20 #define sof(x) sizeof(x)
 21 #define lc(x) (x << 1)
 22 #define rc(x) (x << 1 | 1)
 23 #define lowbit(x) (x & (-x))
 24 #define ll long long
 25 
 26 #define CC 1011
 27 #define MM 102011
 28 
 29 int L[MM], R[MM], U[MM], D[MM], C[MM], X[MM];
 30 int H[CC], S[CC], Q[CC];
 31 int size, n, m;
 32 
 33 void remove(int c) {
 34     R[L[c]] = R[c], L[R[c]] = L[c];
 35     for(int i = D[c]; i != c; i = D[i])
 36         for(int j = R[i]; j != i; j = R[j])
 37             U[D[j]] = U[j], D[U[j]] = D[j], --S[C[j]];
 38 }
 39 
 40 void resume(int c) {
 41     R[L[c]] = L[R[c]] = c;
 42     for(int i = U[c]; i != c; i = U[i])
 43         for(int j = L[i]; j != i ; j = L[j])
 44             ++S[C[U[D[j]] = D[U[j]] = j]];
 45 }
 46 
 47 bool Dance(int k) {
 48     int c = -1;
 49     if(!R[0]) {
 50         printf("%d", k);
 51         for(int i = 0; i < k; i++) printf(" %d", X[Q[i]]);
 52         puts("");
 53         return true;
 54     }
 55     for(int tmp = CC, i = R[0]; i; i = R[i])
 56         if(S[i] < tmp) tmp = S[c=i];
 57     remove(c);
 58     for(int i = D[c]; i != c; i = D[i]) {
 59         Q[k] = i;
 60         for(int j = R[i]; j != i; j = R[j]) remove(C[j]);
 61         if(Dance(k + 1)) return true;
 62         for(int j = L[i]; j != i; j = L[j]) resume(C[j]);
 63     }
 64     resume(c);
 65     return false;
 66 }
 67 
 68 void Link(int r, int c) {
 69     ++S[C[size] = c];
 70     D[size] = D[c];
 71     U[D[c]] = size;
 72     U[size] = c;
 73     D[c] = size;
 74     if(H[r] < 0) H[r] = L[size] = R[size] = size;
 75     else {
 76         R[size] = R[H[r]];
 77         L[R[H[r]]] = size;
 78         L[size] = H[r];
 79         R[H[r]] = size;
 80     }
 81     X[size++] = r;
 82 }
 83 
 84 int main() {
 85     int num;
 86     while(~scanf("%d%d", &n, &m)) {
 87         for(int i = 0; i <= m; i++) {
 88             S[i] = 0;
 89             D[i] = U[i] = i;
 90             L[i+1] = i;
 91             R[i] = i + 1;
 92         }
 93         R[m] = 0;
 94         L[0] = m;
 95         size = m + 1;
 96         for(int i = 1, j; i <= n; i++) {
 97             H[i] = -1;//记得要先置行头指针为-1
 98             scanf("%d", &num);
 99             while(num--) {
100                 scanf("%d", &j);
101                 Link(i, j);
102             }
103         }
104         if(!Dance(0)) puts("NO");
105     }
106     return 0;
107 }
108