现在的位置: 首页 > 综合 > 正文

POJ 3740 Easy Finding(DLX精确覆盖裸题)

2018年10月12日 ⁄ 综合 ⁄ 共 1403字 ⁄ 字号 评论关闭

POJ 3740 Easy Finding

题目链接

题意:选一些行,要求每行正好覆盖一个列

思路:精确覆盖裸题

代码:

#include <cstdio>
#include <cstring>

using namespace std;

const int MAXNODE = 500010;
const int MAXN = 510;
const int MAXM = 1010;

const int INF = 0x3f3f3f3f;

struct DLX {

    int n, m, size;

    int U[MAXNODE], D[MAXNODE], R[MAXNODE], L[MAXNODE], row[MAXNODE], col[MAXNODE];
    int H[MAXN], S[MAXM];
    int ansd, ans[MAXN];

    void init(int n, int m) {
		this->n = n;
		this->m = m;
		ansd = INF;
        for(int i = 0; i <= m; i++) {
            S[i] = 0;
            U[i] = D[i] = i;
            L[i] = i - 1;
            R[i] = i + 1;
        }
        R[m] = 0; L[0] = m;
        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]) {
                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;
    }

    bool Dance(int d) {
        if(R[0] == 0)
            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]) {
            for(int j = R[i]; j != i; j = R[j]) remove(col[j]);
            if (Dance(d + 1)) return true;
            for(int j = L[i]; j != i; j = L[j]) resume(col[j]);
        }
        resume(c);
		return false;
    }
} gao;

int n, m;

int main() {
	while (~scanf("%d%d", &n, &m)) {
		gao.init(n, m);
		for (int i = 1; i <= n; i++)
			for (int j = 1; j <= m; j++) {
				int k;
				scanf("%d", &k);
				if (k) gao.Link(i, j);
			}
		printf("%s\n", gao.Dance(0) ? "Yes, I found it" : "It is impossible");
	}
    return 0;
}

抱歉!评论已关闭.