Time Limit: 1000MS | Memory Limit: 65536K | |
Total Submissions: 16128 | Accepted: 4321 |
Description
Input
Output
Sample Input
3 3 0 1 0 0 0 1 1 0 0 4 4 0 0 0 1 1 0 0 0 1 1 0 1 0 1 0 0
Sample Output
Yes, I found it It is impossible
題意:給出一個矩陣,問是否存在一些行使得每一列有且只有一個1。
思路:Dancing Links。詳見http://www.cnblogs.com/grenet/p/3145800.html
AC代碼:
#include <cstdio>
#include <cstring>
#include <iostream>
#include <cmath>
#include <algorithm>
#include <bitset>
#include <queue>
#define ll long long
using namespace std;
const int maxn = 6005;
const int INF = 1e9;
int n, m, cnt, head;
int L[maxn], R[maxn], U[maxn], D[maxn], S[maxn], C[maxn], H[maxn];
inline void add_link(int i, int j){
C[++cnt] = j;
S[j]++;
D[cnt] = j;
U[cnt] = U[j];
if(H[i]) R[cnt] = H[i], L[cnt] = L[H[i]];
else R[cnt] = L[cnt] = cnt;
H[i] = cnt;
U[D[cnt]] = cnt;
D[U[cnt]] = cnt;
R[L[cnt]] = cnt;
L[R[cnt]] = cnt;
}
void remove(int c){
R[L[c]] = R[c];
L[R[c]] = L[c];
for(int i = D[c]; i != c; i = D[i])
for(int j = R[i]; j != i; j = R[j])
{
U[D[j]] = U[j];
D[U[j]] = D[j];
S[C[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])
{
D[U[j]] = j;
U[D[j]] = j;
S[C[j]]++;
}
L[R[c]] = R[L[c]] = c;
}
bool dance(){
if(R[head] == head)
{
puts("Yes, I found it");
return true;
}
int s = INF, c;
for(int i = R[head]; i != head; i = R[i])
if(S[i] < s) s = S[c = i];
remove(c);
for(int i = D[c]; i != c; i = D[i])
{
for(int j = R[i]; j != i; j = R[j]) remove(C[j]);
if(dance()) return true;
for(int j = L[i]; j != i; j = L[j]) resume(C[j]);
}
resume(c);
return false;
}
int main()
{
int c;
head = 0;
while(~scanf("%d%d", &n, &m))
{
cnt = m;
for(int i =- 0; i <= m; i++)
{
C[i] = U[i] = D[i] = i;
L[i + 1] = i;
R[i] = i + 1;
S[i] = 0;
}
L[0] = m, R[m] = 0;
for(int i = 1; i <= n; i++)
{
H[i] = 0;
for(int j = 1; j <= m; j++)
{
c = getchar();
while(!isdigit(c)) c = getchar();
if(c == '1') add_link(i, j);
}
}
if (!dance()) puts("It is impossible");
}
return 0;
}