最基础的dancing links的精确覆盖题目
1 #include <iostream> 2 #include <cstring> 3 #include <cstdio> 4 #include <algorithm> 5 6 using namespace std; 7 #define N 1005 8 #define MAXN 1000100 9 10 struct DLX{ 11 int n , m , size;//size表示当前dlx表中有多少个元素 12 int ans[N] , k;//ans[]记录选取的行 13 int U[MAXN] , D[MAXN] , L[MAXN] , R[MAXN]; 14 int row[MAXN] , col[MAXN] ; // 分别表示第 i 号节点属于第几行或者第几列 15 int cnt_col[N];//分别表示第i行或者第i列有多少个节点 16 int first[N]; //行上的起始指针 17 18 void init(int _n , int _m) 19 { 20 n = _n , m = _m; 21 size = m; 22 for(int i=0 ; i<=m ; i++){ 23 U[i] = D[i] = i; 24 L[i] = i-1 , R[i] = i+1; 25 } 26 L[0] = m , R[m] = 0; 27 for(int i=1 ; i<=n ; i++) first[i]=-1; 28 for(int i=1 ; i<=m ; i++) cnt_col[i] = 0; 29 // for(int i=0 ; i<=n ; i++) cout<<"here: "<<i<<" "<<L[i]<<" "<<R[i]<<endl; 30 } 31 32 void link(int r , int c) 33 { 34 ++size; 35 //修改列上的情况 36 D[size] = D[c] , U[D[c]] = size; 37 U[size] = c , D[c] = size; 38 cnt_col[c]++ , col[size] = c ; 39 40 //修改行上的情况 41 if(first[r]<0) first[r] = L[size] = R[size] = size; 42 else{ 43 R[size] = R[first[r]] , L[R[first[r]]] = size; 44 L[size] = first[r] , R[first[r]] = size; 45 } 46 // cout<<" r: "<<r<<" c: "<<c<<" "<<size<<" "<<L[size]<<" "<<R[size]<<" "<<U[size]<<" "<<D[size]<<endl; 47 row[size] = r; 48 } 49 50 void Remove(int c) 51 { 52 L[R[c]] = L[c] , R[L[c]] = R[c]; 53 for(int i=D[c] ; i!=c ; i=D[i]){ 54 for(int j=R[i] ; j!=i ; j=R[j]){ 55 D[U[j]] = D[j] , U[D[j]] = U[j]; 56 --cnt_col[col[j]]; 57 } 58 } 59 } 60 61 void Resume(int c) 62 { 63 for(int i=U[c] ; i!=c ; i=U[i]){ 64 for(int j=L[i] ; j!=i ; j=L[j]){ 65 U[D[j]] = D[U[j]] = j; 66 ++cnt_col[col[j]]; 67 } 68 } 69 R[L[c]] = L[R[c]] = c; 70 } 71 72 bool Dance(int d) 73 { 74 75 if(!R[0]){ 76 k = d; 77 return true; 78 } 79 int st = R[0]; 80 //找到能删除最少节点的列先删除,这样递归的行的次数就会减少,提高效率 81 for(int i=st ; i!=0 ; i=R[i]){ 82 if(cnt_col[st]>cnt_col[i]) 83 st = i; 84 } 85 86 Remove(st); 87 for(int i=D[st] ; i!=st ; i=D[i]){ 88 ans[d] = row[i]; 89 for(int j=R[i] ; j!=i ; j=R[j]) Remove(col[j]); 90 if(Dance(d+1)) return true; 91 for(int j=L[i] ; j!=i ; j=L[j]) Resume(col[j]); 92 } 93 Resume(st); 94 return false; 95 } 96 }dlx; 97 98 int main() 99 { 100 // freopen("a.in" , "r" , stdin); 101 int n , m; 102 103 while(~scanf("%d%d" , &n , &m)) 104 { 105 dlx.init(n , m); 106 for(int r=1 ; r<=n ; r++){ 107 int m , c; 108 scanf("%d" , &m); 109 for(int i=0 ; i<m ; i++){ 110 scanf("%d" , &c); 111 dlx.link(r , c); 112 } 113 } 114 bool ok = dlx.Dance(0); 115 if(ok){ 116 printf("%d" , dlx.k); 117 sort(dlx.ans , dlx.ans+dlx.k); 118 for(int i=0 ; i<dlx.k ; i++) printf(" %d" , dlx.ans[i]); 119 puts(""); 120 } 121 else puts("NO"); 122 } 123 return 0; 124 }