hust 1017 dancing links 精确覆盖模板题

最基础的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 }

 

你可能感兴趣的:(link)