POJ3740Easy Finding(DLX入门)

->题目请戳这里<-

题目大意:给一个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


你可能感兴趣的:(数据结构,dlx)