您的位置:首页 > 其它

Hust1017 Exact cover 【精确覆盖】

2013-03-31 02:19 330 查看
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
, S
, mark[V];
int size , n , m , OK
, 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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: