您的位置:首页 > 其它

hust 1017 dancing links 精确覆盖模板题

2015-05-15 00:38 344 查看
最基础的dancing links的精确覆盖题目

#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>

using namespace std;
#define N 1005
#define MAXN 1000100

struct DLX{
int n , m , size;//size表示当前dlx表中有多少个元素
int ans
, k;//ans[]记录选取的行
int U[MAXN] , D[MAXN] , L[MAXN] , R[MAXN];
int row[MAXN] , col[MAXN] ; // 分别表示第 i 号节点属于第几行或者第几列
int cnt_col
;//分别表示第i行或者第i列有多少个节点
int first
; //行上的起始指针

void init(int _n , int _m)
{
n = _n , m = _m;
size = m;
for(int i=0 ; i<=m ; i++){
U[i] = D[i] = i;
L[i] = i-1 , R[i] = i+1;
}
L[0] = m , R[m] = 0;
for(int i=1 ; i<=n ; i++) first[i]=-1;
for(int i=1 ; i<=m ; i++) cnt_col[i] = 0;
// for(int i=0 ; i<=n ; i++)  cout<<"here: "<<i<<" "<<L[i]<<" "<<R[i]<<endl;
}

void link(int r , int c)
{
++size;
//修改列上的情况
D[size] = D[c] , U[D[c]] = size;
U[size] = c , D[c] = size;
cnt_col[c]++ , col[size] = c ;

//修改行上的情况
if(first[r]<0) first[r] = L[size] = R[size] = size;
else{
R[size] = R[first[r]] , L[R[first[r]]] = size;
L[size] = first[r] , R[first[r]] = size;
}
//  cout<<" r: "<<r<<" c: "<<c<<" "<<size<<" "<<L[size]<<" "<<R[size]<<" "<<U[size]<<" "<<D[size]<<endl;
row[size] = r;
}

void Remove(int c)
{
L[R[c]] = L[c] , R[L[c]] = R[c];
for(int i=D[c] ; i!=c ; i=D[i]){
for(int j=R[i] ; j!=i ; j=R[j]){
D[U[j]] = D[j] , U[D[j]] = U[j];
--cnt_col[col[j]];
}
}
}

void Resume(int c)
{
for(int i=U[c] ; i!=c ; i=U[i]){
for(int j=L[i] ; j!=i ; j=L[j]){
U[D[j]] = D[U[j]] = j;
++cnt_col[col[j]];
}
}
R[L[c]] = L[R[c]] = c;
}

bool Dance(int d)
{

if(!R[0]){
k = d;
return true;
}
int st = R[0];
//找到能删除最少节点的列先删除,这样递归的行的次数就会减少,提高效率
for(int i=st ; i!=0 ; i=R[i]){
if(cnt_col[st]>cnt_col[i])
st = i;
}

Remove(st);
for(int i=D[st] ; i!=st ; i=D[i]){
ans[d] = row[i];
for(int j=R[i] ; j!=i ; j=R[j]) Remove(col[j]);
if(Dance(d+1)) return true;
for(int j=L[i] ; j!=i ; j=L[j]) Resume(col[j]);
}
Resume(st);
return false;
}
}dlx;

int main()
{
// freopen("a.in" , "r" , stdin);
int n , m;

while(~scanf("%d%d" , &n , &m))
{
dlx.init(n , m);
for(int r=1 ; r<=n ; r++){
int m , c;
scanf("%d" , &m);
for(int i=0 ; i<m ; i++){
scanf("%d" , &c);
dlx.link(r , c);
}
}
bool ok = dlx.Dance(0);
if(ok){
printf("%d" , dlx.k);
sort(dlx.ans , dlx.ans+dlx.k);
for(int i=0 ; i<dlx.k ; i++) printf(" %d" , dlx.ans[i]);
puts("");
}
else puts("NO");
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: