HUST 1017 Exact cover(Dancing Links)(精确覆盖问题)
2016-01-18 17:31
435 查看
Exact cover
题目链接:
http://acm.hust.edu.cn/problem/show/1017解题思路:
题目大意:本题就是给你一个由0,1元素组成的矩阵,问取出哪几行,可以使这几行构成的新矩阵,每列只有一个1.
算法思想:
Dancing Links模板题。
如果有人还不了解双向链表的人可以先看一下这位大牛的博客:http://blog.sina.com.cn/s/blog_7d44748b01013fsf.html
不过Dancing Links并不是双向链表,而是十字链表。(ps:记得数据结构书上有提到过,不过本弱并不晓得这东西有什么用,这次算是长知识了。)
学Dancing Links可以参照http://www.cnblogs.com/grenet/p/3145800.html这位神牛的博客。
至于Dancing Links的一些用途,可以看看这位大牛的博客。http://blog.csdn.net/mu399/article/details/7627862
AC代码:
#include <iostream> #include <cstdio> using namespace std; const int maxnode = 100010; const int maxm = 1010; const int maxn = 1010; struct DLX{ int n,m,len; int U[maxnode],D[maxnode],R[maxnode],L[maxnode],Row[maxnode],Col[maxnode]; int H[maxn];//行头结点 int S[maxm];//每列有多少个结点 int ansd,ans[maxn];//如果有答案,则选了ansd行,具体是哪几行放在ans[]数组里面,ans[0~ansd-1] void init(int _n,int _m){ n = _n;m = _m; for(int i = 0; i <= m; i++){ S[i] = 0; U[i] = D[i] = i;//初始状态时,上下都指向自己 L[i] = i-1; R[i] = i+1; } R[m] = 0,L[0] = m; len = m;//编号,每列都有一个头结点,编号1~m for(int i = 1; i <= n; i++) H[i] = -1;//每一行的头结点 } void link(int r,int c){//第r行,第c列 ++S[Col[++len]=c];//第len个节点所在的列为c,当前列的结点数++ Row[len] = r;//第len个结点行位置为r D[len] = D[c]; U[D[c]] = len; U[len] = c; D[c] = len; if(H[r] < 0) H[r] = L[len] = R[len] = len; else{ R[len] = R[H[r]]; L[R[H[r]]] = len; L[len] = H[r]; R[H[r]] = len; } } void del(int c){//删除结点c,以及c上下结点所在的行 //每次调用这个函数,都是从列头节点开始向下删除,这里c也可以理解为第c列 //因为第c列的列头节点编号为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]){ U[D[j]] = U[j]; D[U[j]] = D[j]; --S[Col[j]]; } } } void resume(int c){//回复结点c,以及c上下节点所在的行(同上,也可以理解为从第c列的头节点开始恢复 for(int i = U[c]; i != c; i = U[i]){ for(int j = L[i]; j != i; j = L[j]){ ++S[Col[U[D[j]]=D[U[j]]=j]]; } } L[R[c]] = R[L[c]] = c; } bool dance(int d){//递归深度 if(R[0] == 0){ ansd = d; return true; } int c = R[0]; for(int i = R[0]; i != 0; i = R[i]){ if(S[i] < S[c]) c = i; } del(c);//找到结点数最少的列,当前元素不是原图上0,1的节点,而是列头节点 for(int i = D[c]; i != c; i = D[i]){ ans[d] = Row[i];//列头节点下面的一个节点 for(int j = R[i]; j != i; j = R[j]) del(Col[j]); if(dance(d+1))//找到,返回 return true; for(int j = L[i]; j != i; j = L[j]) resume(Col[j]); } resume(c); return false; } }; DLX head; int main(){ int n,m; while(~scanf("%d%d",&n,&m)){ head.init(n,m); for(int i = 1; i <= n; i++){ int cnt,x; scanf("%d",&cnt); while(cnt--){ scanf("%d",&x); head.link(i,x); } } if(!head.dance(0)) printf("NO\n"); else{ printf("%d",head.ansd); for(int i = 0; i < head.ansd; i++) printf(" %d",head.ans[i]); printf("\n"); } } return 0; }
相关文章推荐
- HUST 1017 Exact cover
- 一切不以Eng 抑或 官网 reference 为参考的 例子都是扯淡
- External Links Module 友情链接模块
- useful open source links
- x
- 跳跃的舞者,舞蹈链(Dancing Links)算法——求解精确覆盖问题
- 通用链接universal links中遇到的问题
- hust1017Exact cover(Dancing Links)
- iPhone开发 – iPhonAn App ID with Identifier 'XX.XX' is not available. Please enter a different string
- FZU 1686 神龙的难题(重复覆盖|Dancing Links)
- hdu 2295 Radar(重复覆盖问题)
- ZOJ 3209 Treasure Map(Dancing Links)(精确覆盖问题)
- 创建通用链接
- Universal links(页面跳转app)
- Linux中硬链接和软连接的介绍
- 2016重走solr长征之路:replication主从同步机制
- C++学习笔记(四)--编程练习第七章
- Android ScrollView嵌套ListView嵌套GridView的上下拉以及加载更多
- RecyclerView Bug:IndexOutOfBoundsException: Inconsistency detected. Invalid view holder adapter的解决方案
- Error: Could not allocate storage for the buffer. Error: Driver load failed.