【题意】:给出一个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<int, int> 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