题目链接:http://poj.org/problem?id=1155
数据结构:https://blog.csdn.net/weixin_39778570/article/details/86484040
ACM题集:https://blog.csdn.net/weixin_39778570/article/details/83187443
题意
给你一个N*M的01矩阵,问是否能否找到一些行,使得每一列有且只有一个1
题解
算法讲解:https://mp.weixin.qq.com/s/2qgFaWUhdt7KlG2l2VlKQA
讲得挺好的,我就不重复了,233
Code
#include<stdio.h>
#include<cstring>
using namespace std;
const int N = 305, M = 25, ID=N*M; // 节点数
struct DLX{
int n,m,size;
int U[ID],D[ID],L[ID],R[ID],Row[ID],Col[ID];
int H[N], S[M];
int ansd,ans[N];
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;
}
L[0] = m;
R[m] = 0;
size = m;
for(int i=1; i<=n; i++){
H[i] = -1;
}
}
void link(int r, int c){
++S[Col[++size]=c];
Row[size] = r;
D[size] = D[c];
U[D[c]] = size;
U[size] = c;
D[c] = size;
if(H[r]<0){
H[r] = L[size] = R[size] = size;
} else{
R[size] = R[H[r]];
L[R[H[r]]] = size;
L[size] = H[r];
R[H[r]] = size;
}
}
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]){ // 该列上其他的1的行删
U[D[j]] = U[j];
D[U[j]] = D[j];
--S[Col[j]];
}
}
}
void resume(int 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;
}
// d为递归深度
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;
}
remove(c); // 指定列
for(int i=D[c]; i!=c; i=D[i ]){
ans[d]=Row[i]; // 选中指定列上1的行
for(int j=R[i]; j!=i; j=R[j]){
remove(Col[j]); // 改行上的其它1的列删除
}
if(Dance(d+1))return true;
for(int j=L[i]; j!=i; j=L[j]){
resume(Col[j]);
}
}
resume(c);
return false;
}
};
DLX g;
int main(){
int n,m;
while(scanf("%d%d",&n,&m)!=EOF){
g.init(n,m);
for(int i=1; i<=n; i++){
for(int j=1; j<=m; j++){
int x;scanf("%d",&x);
if(x==1)g.link(i,j);
}
}
if(g.Dance(0))puts("Yes, I found it");
else puts("It is impossible");
}
return 0;
}