Hust1017 Exact cover 【精确覆盖】

http://acm.hust.edu.cn/problem.php?id=1017

There is an N*M matrix with only 0s and 1s, (1 <= N,M <= 1000). 

An exact cover is a selection of rows such that every column has a 1 in exactly one of the selected rows.

Try to find out the selected rows. 

DLX接精确覆盖

 

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <vector>
#include <set>
#include <map>
#include <cmath>
#include <queue>
using namespace std;
template <class T> void checkmin(T &t,T x) {if(x < t) t = x;}
template <class T> void checkmax(T &t,T x) {if(x > t) t = x;}
template <class T> void _checkmin(T &t,T x) {if(t==-1) t = x; if(x < t) t = x;}
template <class T> void _checkmax(T &t,T x) {if(t==-1) t = x; if(x > t) t = x;}
typedef pair <int,int> PII;
typedef pair <double,double> PDD;
typedef long long ll;
#define foreach(it,v) for(__typeof((v).begin()) it = (v).begin(); it != (v).end ; it ++)
const int N = 1100 , V = 102020;
int U[V] , D[V] , L[V] , R[V] , C[V];
int H[N] , S[N] , mark[V];
int size , n , m , OK[N] , flag;
void Link(int r,int c) {
    S[c] ++; C[size] = c;
    U[size] = U[c]; D[U[c]] = size;
    D[size] = c; U[c] = size;
    if(H[r] == -1) H[r]=L[size]=R[size]=size;
    else {
        L[size]=L[H[r]];R[L[H[r]]]=size;
        R[size]=H[r];L[H[r]]=size;
    }
    mark[size] = r;
    size ++;
}
void remove(int c) { //delete column
    int i , j;
    L[R[c]] = L[c];
    R[L[c]] = R[c];
    for(i=D[c];i!=c;i=D[i]) {
        for(j=R[i];j!=i;j=R[j]) {
            U[D[j]] = U[j]; D[U[j]] = D[j];
            S[C[j]] --;
        }
    }
}
void resume(int c) {
    int i , j;
    for(i=U[c];i!=c;i=U[i]) {
        for(j=L[i];j!=i;j=L[j]) {
            U[D[j]] = j; D[U[j]] = j;
            S[C[j]] ++;
        }
    }
    L[R[c]] = c;
    R[L[c]] = c;
}
void Dance(int k) {
    int i , j ,Min , c;
    if(!R[0]) {
        flag = 1;
        printf("%d",k);
        for(i=0;i<k;i++)
            printf(" %d",mark[OK[i]]);
        printf("\n");
        return;
    }
    for(Min=N,i=R[0];i;i=R[i])
        if(S[i] < Min) Min = S[i] , c = i;
    remove(c);
    for(i=D[c];i!=c;i=D[i]) {
        OK[k] = i;
        //remove(i);
        for(j=R[i];j!=i;j=R[j])
            remove(C[j]);
        Dance(k+1);
        if(flag) return;
        for(j=L[i];j!=i;j=L[j])
            resume(C[j]);
        //resume(i);
    }
    resume(c);
}
int main() {
    int i , j , num;
    while(~scanf("%d%d",&n,&m)) {
        for(i=0;i<=m;i++) {
            S[i] = 0;
            D[i] = U[i] = i;
            L[i+1] = i; R[i] = i + 1;
        }
        R[m] = 0;
        size = m + 1;
        memset(H,-1,sizeof(H));
        memset(mark,0,sizeof(mark));
        for(i=1;i<=n;i++) {
            scanf("%d",&num);
            while(num --) {
                scanf("%d",&j);
                Link(i , j);
            }
        }
        flag = 0;
        Dance(0);
        if(!flag) puts("NO");
    }
    return 0;
}

 

posted @ 2013-03-31 02:19  aiiYuu  阅读(154)  评论(0编辑  收藏  举报