题意:求任取n行能否使每列有且仅有一个1,
分析:算是数据结构加搜索,由著名的Dancing links解,粘一个
Dancing links详解地址:dancing links详解
我的ac代码(也是看了好长时间上面的文章自己又整理做的,先存了作为模板)
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
const int MAXN=350;
const int MAXM=350;
const int MAXX=MAXN*MAXM+MAXM;
int L[MAXX],R[MAXX],U[MAXX],D[MAXX],H[MAXX],C[MAXX];//UDLR分别为上下左右,H为该节点的行数,C为列数
int hh[MAXN],cc[MAXM];//hh为每行当前节点,cc为每列当前节点,建图使用
int ans[MAXN],n,m,cnt,head;
void init()
{
int i;head=0;
for(i=1;i<=n;i++)
hh[i]=-1;
for(i=0;i<=m;i++)
{
cc[i]=i;
L[i+1]=i;
R[i]=i+1;
U[i]=D[i]=i;
H[i]=0;
C[i]=i;
}
L[0]=m;
R[m]=0;
cnt=m+1;
}
void insert(int a,int b)
{
H[cnt]=a,C[cnt]=b;
if(hh[a]==-1) L[cnt]=R[cnt]=cnt;
else
{
L[cnt]=hh[a];
L[R[hh[a]]]=cnt;
R[cnt]=R[hh[a]];
R[hh[a]]=cnt;
}
U[cnt]=cc[b];
U[D[cc[b]]]=cnt;
D[cnt]=D[cc[b]];
D[cc[b]]=cnt;
hh[a]=cnt;
cc[b]=cnt;
cnt++;
}
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])
{
D[U[j]]=D[j];
U[D[j]]=U[j];
}
}
void resume(int c)
{
L[R[c]]=c;
R[L[c]]=c;
for(int i=U[c];i!=c;i=U[i])
for(int j=R[i];j!=i;j=R[j])
{
U[D[j]]=j;
D[U[j]]=j;
}
}
bool dance(int k)
{
int i,j,c=R[head];
if(c==head)/*Showpath*/return true;
remove(c);
for(i=D[c];i!=c;i=D[i])
{
ans[k]=H[i];
for(j=R[i];j!=i;j=R[j])remove(C[j]);
if(dance(k+1))return true;
for(j=L[i];j!=i;j=L[j])resume(C[j]);
}
resume(c);
return false;
}
int main()
{
int i,j,x;
//freopen("123.txt","r",stdin);
while(~scanf("%d%d",&n,&m))
{
init();
for(i=1;i<=n;i++)
for(j=1;j<=m;j++)
{
scanf("%d",&x);
if(x)insert(i,j);
}
if(dance(0))printf("Yes, I found it\n");
else printf("It is impossible\n");
}
return 0;
}