->题目请戳这里<-
题目大意:给一个m*n的01矩阵,求是否存在若干行,使这些行中的1覆盖所有的列恰好1次。
题目分析:裸的精确覆盖题目,建图+模版= AC。需要用到dance links这种数据结构优化。dancing links也是最近才学,今天刚弄明白,这此特别感谢yyd大牛,帮我解决了一个小瓶颈。
关于dancing links,仔细研究才能发现dancing lingks是如此绝妙的数据结构,优雅的代码,超高的效率,无不让人惊叹,欢迎进入dancing links的世界:
Knuth原版论文:http://wenku.baidu.com/view/60eb28ded15abe23482f4d77.html
中文翻译:http://wenku.baidu.com/view/d8f13dc45fbfc77da269b126.html
关于本题,详情请见代码:
#include <iostream> #include<cstdio> #include<cstring> using namespace std; const int N = 305; const int M = 20; const int MX = N * M; int m,n; int head,size; int s[MX],u[MX],d[MX],l[MX],r[MX],h[MX],col[MX],row[MX]; void init() { head = 0; memset(s,0,sizeof(s)); int i; for(i = 0;i <= n;i ++) { r[i] = (i + 1) % (n + 1); l[i] = (i - 1 + n + 1) % (n + 1); u[i] = d[i] = i; } size = n + 1; memset(h,0,sizeof(h)); } void remove(int c) { l[r[c]] = l[c]; r[l[c]] = r[c]; int i,j; for(i = d[c];i != c;i = d[i]) { for(j = r[i];j != i;j = r[j]) { u[d[j]] = u[j]; d[u[j]] = d[j]; s[col[j]] --; } } } void recover(int c) { int i,j; for(i = u[c];i != c;i = u[i]) { for(j = l[i];j != i;j = l[j]) { s[col[j]] ++; u[d[j]] = d[u[j]] = j; } } l[r[c]] = r[l[c]] = c; } void insert(int i,int j) { s[j] ++;//第j列增加一个元素 if(h[i])//第i行已经有元素了,h[i]记录第i行第一个元素地址 { r[size] = h[i]; l[size] = l[h[i]]; l[r[size]] = size; r[l[size]] = size; } else { h[i] = size; l[size] = r[size] = size; } u[size] = u[j]; d[size] = j; d[u[j]] = size; u[j] = size; col[size] = j;//该点属于第j列 row[size] = i;//该点属于第i行 size ++; } bool dfs(int k) { if(head == r[head]) return true; int mn = MX; int cur; int i,j; for(i = r[head];i != head;i = r[i]) { if(s[i] < mn) { mn = s[i]; cur = i; } } remove(cur); for(i = d[cur];i != cur;i = d[i]) { for(j = r[i];j != i;j = r[j]) remove(col[j]); if(dfs(k + 1)) return true; for(j = r[i];j != i;j = r[j]) recover(col[j]); } recover(cur); return false; } int main() { int i,j,t; while(scanf("%d%d",&m,&n) != EOF) { init();//初始化列头 for(i = 1;i <= m;i ++) { for(j = 1;j <= n;j ++) { scanf("%d",&t); if(t) insert(i,j); } } if(dfs(0) == false) { printf("It is impossible\n"); } else { printf("Yes, I found it\n"); } } return 0; } //276K 360MS