给出一个\(n\times m\)的01矩阵,每行最多有\(c\)个1,求一个精确覆盖,即选出一些行使得每列有有且仅有一个1。输出方案。

分析

被这个题坑到了啊!!第一次上HUSTOJ做题,不知道没有ONLINE_JUDGE编译参数,又WA了几个小时。

我感觉这个spj是有问题的,只处理了顺序不同的问题,而没有处理方案不同,所以其实有些对的代码过不了。

我最开始看完这篇写的超级棒,主要是配了图的教程,然后自己乱写一个,发现很好写,才45行左右,然后就WA了。最终知道了是ONLINE_JUDGE的问题,但是,把之前的代码去掉文件读写还是会错!

WA的过程中,我去网上搜了很多题解。我要批判一下那些人啊,全都拿别人的代码来当模版……哎。

我在他们的代码中发现了一个优化。原来的教程中说的是找到Head右边的第一个开始搜索。其实搜索的顺序是无关的,因为这是基于所有的列都会被覆盖到,所以顺序无关。所以我们可以找其中列标下面剩余1的个数最少的那一列来找,可以大大剪枝。所以每一列维护一下size即可。

还有一个要注意的地方,我们在删除列和回退的时候,方向是不一样的。比如说,删除列我们一开始向下走走一圈,那么回退的时候我们向上走,估计是为了避免一些冲突。同样在便利我们要删除的行的时候,从左到右,回退从右到左。

代码

网上那些“模版”写得那么奇怪还一堆人拿来抄。这个多漂亮~

#include<cstdio>
#include<cctype>
#include<cstring>
#include<algorithm>
using namespace std;
int read() {
int x=0,f=1;
char c=getchar();
for (;!isdigit(c);c=getchar()) if (c=='-') f=-1;
for (;isdigit(c);c=getchar()) x=x*10+c-'0';
return x*f;
}
const int maxn=1e3+10;
const int maxc=1e2+10;
const int maxp=maxn*maxc;
int a[maxc],ans[maxn];
struct node {
int l,r,u,d,col,row;
};
struct DLX {
node p[maxp];
int tot,last[maxn],size[maxn];
void clear(int m) {
tot=m;
memset(last,0,sizeof last);
memset(size,0,sizeof size);
memset(p,0,sizeof p);
p[0]=(node){0,0,0,0,0,0};
for (int i=1;i<=m;++i) {
last[i]=i;
p[i]=(node){i-1,p[i-1].r,i,i,i,0};
p[p[i].l].r=i,p[p[i].r].l=i;
}
}
void build(int row,int a[],int len) {
p[++tot]=(node){tot,tot,last[a[1]],p[last[a[1]]].d,a[1],row};
p[p[tot].u].d=p[p[tot].d].u=last[a[1]]=tot;
++size[p[tot].col];
for (int i=2;i<=len;++i) {
int x=a[i];
p[++tot]=(node){tot-1,p[tot-1].r,last[x],p[last[x]].d,x,row};
p[p[tot].l].r=p[p[tot].r].l=p[p[tot].u].d=p[p[tot].d].u=last[x]=tot;
++size[p[tot].col];
}
}
void del(int c) {
p[p[c].l].r=p[c].r,p[p[c].r].l=p[c].l;
for (int i=p[c].d;i!=c;i=p[i].d) for (int j=p[i].r;j!=i;j=p[j].r) p[p[j].u].d=p[j].d,p[p[j].d].u=p[j].u,--size[p[j].col];
}
void back(int c) {
p[p[c].l].r=p[p[c].r].l=c;
for (int i=p[c].u;i!=c;i=p[i].u) for (int j=p[i].r;j!=i;j=p[j].r) p[p[j].u].d=p[p[j].d].u=j,++size[p[j].col];
}
int dance(int k) {
if (p[0].r==0) return k;
int first,mi=maxp;
for (int i=p[0].r;i;i=p[i].r) if (size[i]<mi) mi=size[i],first=i; //here
if (p[first].d==first) return 0;
del(first);
for (int i=p[first].d;i!=first;i=p[i].d) {
for (int j=p[i].r;j!=i;j=p[j].r) del(p[j].col);
ans[k+1]=p[i].row;
int ret=dance(k+1);
if (ret) return ret;
ans[k+1]=0;
for (int j=p[i].l;j!=i;j=p[j].l) back(p[j].col);
}
back(first);
return 0;
}
} dlx;
int main() {
int n,m;
while (~scanf("%d%d",&n,&m)) {
dlx.clear(m);
for (int i=1;i<=n;++i) {
int c=read();
if (!c) continue;
for (int j=1;j<=c;++j) a[j]=read();
sort(a+1,a+c+1);
dlx.build(i,a,c);
}
int gs=dlx.dance(0);
if (!gs) {
puts("NO");
continue;
}
printf("%d ",gs);
sort(ans+1,ans+gs+1);
for (int i=1;i<=gs;++i) printf("%d ",ans[i]);
puts("");
}
return 0;
}

HUST1017-Exact Cover的更多相关文章

  1. HUST1017 Exact cover —— Dancing Links 精确覆盖 模板题

    题目链接:https://vjudge.net/problem/HUST-1017 1017 - Exact cover 时间限制:15秒 内存限制:128兆 自定评测 7673 次提交 3898 次 ...

  2. HUST 1017 - Exact cover (Dancing Links 模板题)

    1017 - Exact cover 时间限制:15秒 内存限制:128兆 自定评测 5584 次提交 2975 次通过 题目描述 There is an N*M matrix with only 0 ...

  3. Dancing Links and Exact Cover

    1. Exact Cover Problem DLX是用来解决精确覆盖问题行之有效的算法. 在讲解DLX之前,我们先了解一下什么是精确覆盖问题(Exact Cover Problem)? 1.1 Po ...

  4. Dancing Link --- 模板题 HUST 1017 - Exact cover

    1017 - Exact cover Problem's Link:   http://acm.hust.edu.cn/problem/show/1017 Mean: 给定一个由0-1组成的矩阵,是否 ...

  5. HUST 1017 Exact cover (Dancing links)

    1017 - Exact cover 时间限制:15秒 内存限制:128兆 自定评测 6110 次提交 3226 次通过 题目描述 There is an N*M matrix with only 0 ...

  6. [HUST 1017] Exact cover

    Exact cover Time Limit: 15s Memory Limit: 128MB Special Judge Submissions: 6012 Solved: 3185 DESCRIP ...

  7. hustoj 1017 - Exact cover dancing link

    1017 - Exact cover Time Limit: 15s Memory Limit: 128MB Special Judge Submissions: 5851 Solved: 3092 ...

  8. 搜索(DLX):HOJ 1017 - Exact cover

    1017 - Exact cover Time Limit: 15s Memory Limit: 128MB Special Judge Submissions: 6751 Solved: 3519 ...

  9. [HDU1017]Exact cover[DLX][Dancing Links详解][注释例程学习法]

    Dancing Links解决Exact Cover问题. 用到了循环双向十字链表. dfs. 论文一知半解地看了一遍,搜出一篇AC的源码,用注释的方法帮助理解. HIT ACM 感谢源码po主.链接 ...

  10. [ACM] HUST 1017 Exact cover (Dancing Links,DLX模板题)

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

随机推荐

  1. gitlab在push代码的时候报错

    一.问题报错 gitlab在执行git pull origin master,拉取代码的时候报如下错误. $ git pull origin master remote: Counting objec ...

  2. OpenStack入门篇(三)之KVM介绍及安装

    1.什么是虚拟化? 虚拟化是云计算的基础.简单的说,虚拟化使得在一台物理的服务器上可以跑多台虚拟机,虚拟机共享物理机的 CPU.内存.IO 硬件资源,但逻辑上虚拟机之间是相互隔离的. 物理机我们一般称 ...

  3. pandaboard es 制作SD启动卡OMAP4460

    1. 本次使用的是chipsee的板子,带屏幕的,先把资料传到Ubuntu的共享目录下 2. 进入共享目录 /mnt/hgfs/ubuntu_share/pandboard_es_linux# 3. ...

  4. C# TTS-文本转语音

    System.Speech 命名空间包含支持语音识别的类型,你可以从Visual Studio很方便的添加相关组件的引用. System.Speech相关介绍:https://msdn.microso ...

  5. TPO 02 - Early Cinema

    TPO 02 - Early Cinema NOTE: 主要意思(大概就是主谓宾)用粗体标出:重要的其它用斜体: []中的是大致意思,可能与原文有关也可能无关,但不会离题 目的为训练句子/段落总结能力 ...

  6. 借助全新 MATLAB® 适配器代码示例读取英特尔® 实感™ 摄像头数据流

    下载源代码请访问原文地址:借助全新 MATLAB® 适配器代码示例读取英特尔® 实感™ 摄像头数据流 简介 该可下载代码示例简要介绍了如何使用英特尔® 实感™ SDK 和 MATLAB 的图像采集工具 ...

  7. 十几行代码带你用Python批量实现txt转xls,方便快捷

    前天看到后台有一兄弟发消息说目前自己有很多txt 文件,领导要转成xls文件,问用python怎么实现,我在后台简单回复了下,其实完成这个需求方法有很多,因为具体的txt格式不清楚,当然如果是有明确分 ...

  8. 【转】lvs、nginx、haproxy转发模式优缺点总结

    原文地址: https://yq.aliyun.com/ziliao/78374 一.LVS转发模式 LVS是章文嵩博士写的一个工作于四层的高可能性软件.不像后两者支持七层转发,不过也正因为其简单,所 ...

  9. Tomcat源码学习(2)——启动过程分析

    Tomcat启动过程分析 启动 tomcat 时,Windows下执行 startup.bat :Linux下执行 startup.sh 文件,实际上最后都是调用 org.apache.catalin ...

  10. sqli-labs学习笔记 DAY3

    DAY 3 sqli-labs lesson 6 同lesson 5,只是把单引号改为双引号 sqli-labs lesson 7 同lesson 5,只是把单引号后面加两个空格,使用Burpsuit ...