HUST 1017 Exact cover 跳舞链(DLX) 模板题目
http://acm.hust.edu.cn:8080/judge/problem/viewProblem.action?id=10702
题意:
给你一个n*m的01矩阵,让你选择若干行使这些行中的1能够覆盖所有的列,而且不能出现重复覆盖。输出所选的行。
思路:
这是跳舞链的模板题目。不多说了。
给出个人觉得讲解比较好的链接:http://blog.csdn.net/mu399/article/details/7627736
参考代码:http://blog.csdn.net/dooder_daodao/article/details/6654904
我的代码:
View Code
#include <cstdio> #include <cstring> #include <iostream> using namespace std; #define CL(a,num) memset((a),(num),sizeof(a)) #define inf 0x7f7f7f7f #define M 1007 #define N 1000007 const int head = 0; int u[N],d[N],l[N],r[N],c[N],row[N]; int s[M],o[M]; int ak,n,m; void init(int m){ int i; for (i = 1; i <= m; ++i){ l[i] = i - 1; r[i] = i + 1; u[i] = d[i] = i; c[i] = i; s[i] = 0; } l[head] = m; r[head] = 1; r[m] = head; } void remove(int ci){ int i,j; l[r[ci]] = l[ci]; r[l[ci]] = r[ci]; for (i = d[ci]; i != ci; 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 ci){ int i,j; l[r[ci]] = r[l[ci]] = ci; for (i = u[ci]; i != ci; i = u[i]){ for (j = l[i]; j != i; j = l[j]){ u[d[j]] = d[u[j]] = j; s[c[j]]++; } } } int dfs(int k){ int i,j; //若列对象为空,说明所有列已经覆盖,返回值 if (r[head] == head){ ak = k; return 1; } //每次着该列里面1最少的 int MIN = inf, ci = 0; for (i = r[head]; i != head; i = r[i]){ if (s[i] < MIN){ MIN = s[i]; ci = i; } } remove(ci);//删除该列对象以及该列所覆盖的行 for (i = d[ci]; i != ci; i = d[i]){ for (j = r[i]; j != i; j = r[j]){ remove(c[j]);//选择i作为覆盖c列的行,并且要删调该行所覆盖的列 } o[k] = row[i];//记录结果 if (dfs(k + 1)) return 1;//继续选择列 //i列不能满足还原i列 for (j = l[i]; j != i; j = l[j]){ resume(c[j]); } } resume(ci); return 0; } int main(){ int i,j; int num,size; while (~scanf("%d%d",&n,&m)){ //更新列对象 init(m); size = m + 1;//记录第几个 int x; for (i = 0; i < n; ++i){ scanf("%d",&num); int rh = -1; for (j = 0; j < num; ++j){ scanf("%d",&x); s[x]++;//记录x列有多少个1 c[size] = x;//记录第size个的列 row[size] = i + 1;//记录第size个的行 //插入列,挂链 u[size] = u[x]; d[u[x]] = size; u[x] = size; d[size] = x; //插入行,挂链 if (rh == -1){ l[size] = r[size] = size; rh = size; } else{ l[size] = l[rh]; r[l[rh]] = size; l[rh] = size; r[size] = rh; } size++; } } if (dfs(0)){ printf("%d",ak); for (i = 0; i < ak; ++i) printf(" %d",o[i]); printf("\n"); } else{ printf("NO\n"); } } return 0; }