【HUST - 1017】精确覆盖问题 Exact Cover DLX 解题报告
2016-07-11 11:24
344 查看
Exact cover
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.
Input
There are multiply test cases. First line: two integers N, M; The following N lines: Every line first comes an integer C(1 <= C <= 100), represents the number of 1s in this row, then comes C integers: the index of the columns whose value is 1 in this row.
Output
First output the number of rows in the selection, then output the index of the selected rows. If there are multiply selections, you should just output any of them. If there are no selection, just output "NO".
Sample Input
6 73 1 4 72 1 43 3 5 63 4 5 72 2 74 2 3 6 7
Sample Output
Source
dupeng
DLX。。
直接贴代码,有注释(原谅我生性懒惰)
Time Limit: 15000MS | Memory Limit: 131072KB | 64bit IO Format: %lld & %llu |
Description
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.Input
There are multiply test cases. First line: two integers N, M; The following N lines: Every line first comes an integer C(1 <= C <= 100), represents the number of 1s in this row, then comes C integers: the index of the columns whose value is 1 in this row.
Output
First output the number of rows in the selection, then output the index of the selected rows. If there are multiply selections, you should just output any of them. If there are no selection, just output "NO".
Sample Input
6 73 1 4 72 1 43 3 5 63 4 5 72 2 74 2 3 6 7
Sample Output
3 2 4 6
Source
dupeng
DLX。。
直接贴代码,有注释(原谅我生性懒惰)
#include<cstdio> #define MAXL 1100 int tot,root=0;//root处于最左上角(0,0) int U[MAXL*MAXL],D[MAXL*MAXL],L[MAXL*MAXL],R[MAXL*MAXL];//根据节点编号来获取邻居 int Ccnt[MAXL];//根据pos得到列上节点计数器 int Rrt[MAXL],Crt[MAXL];//根据pos得到行/列上根节点的编号 int Row[MAXL*MAXL],Col[MAXL*MAXL];//根据节点编号得到节点位置 int ans[MAXL],top; 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]){//终究要回到原位 向右删除 //if(!Col[j])continue;//??? //因为 U[D[j]]=U[j];//删除 断开上下的链 D[U[j]]=D[j]; Ccnt[Col[j]]--;//列上节点计数器-1 } } 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; Ccnt[Col[j]]++; } L[R[c]]=R[L[c]]=c; } bool dfs(){ if(R[root]==root)//随便都可以,相当于把所有列都删完了 return true; int minn=10000,at; for(int p=R[root];p!=root;p=R[p]){ if(Ccnt[Col[D[p]]]<minn)//非虚拟节点才能获取row,col的值 所以用D[p] minn=Ccnt[Col[D[p]]],at=p; } Remove(at);//删除一整列 for(int i=D[at];i!=at;i=D[i]){ //表示有行在这一列上为1(相互冲突) ans[top++]=Row[i];//记录答案 for(int j=R[i];j!=i;j=R[j])//删除这一整行(行上为1的节点) Remove(Col[j]);//这里给的是位置????????? //向下深搜(删除) if(dfs())return true; for(int j=L[i];j!=i;j=L[j]) Resume(Col[j]);//这里给的是位置????????? top--; } Resume(at); return false; } char g[MAXL][MAXL]; int main(){ int row,col,begin,end; while(~scanf("%d%d",&row,&col)){ for(int i=0;i<=col;i++)//初始化列的链表表头 编号就是列的编号 Ccnt[i]=0,L[i]=i-1,R[i]=i+1,U[i]=D[i]=i; L[0]=col;//环状连接 R[col]=0; root=0;//归位指针 top=1; tot=col+1;//前面的列已经被编号 所以从col+1开始 for(int i=1;i<=row;i++){ int tmp,t2; scanf("%d",&tmp); begin=end=tot; for(int j=1;j<=tmp;j++){ scanf("%d",&t2); Ccnt[t2]++; Col[tot]=t2; Row[tot]=i; U[tot]=t2;//插入列 D[tot]=D[t2]; U[D[t2]]=tot; D[t2]=tot; L[tot]=end;//插入列 (在队尾) R[tot]=begin; L[begin]=tot; R[end]=tot; end=tot++; } } if(!dfs())puts("NO"); else { printf("%d",top-1); for(int i=1;i<top;i++) printf(" %d",ans[i]); puts(""); } } }
相关文章推荐
- Largest Rectangle in Histogram
- HttpClient请求json数据
- python中json对象转换出错解决方法
- CItrix StoreFront 3 优化
- 可控的纵向图片滚动
- 亮丽的JS图片渐变导航
- mysql修改密码
- android 画笔和画布的使用,实现类似360清除内存的画面
- php数组键值排序
- 移动端web开发的小笔记
- JSP获取绝对路径
- 禁止在图片上使用右键
- 经典的图片切换
- [转]反向代理过程与Nginx特点详解
- Js运动动画系列4--多物体缓冲运动
- leetcode.182. Duplicate Emails
- js+php实现无刷新下载文件
- php中array_column函数简单实现方法
- PHP命名空间(Namespace)的使用详解
- iOS—最全的真机测试教程