HUST_1017_ExactCover(DancingLinksX精确覆盖模板题)

1017 - Exact cover

时间限制:15秒 内存限制:128兆

自定评测 6846 次提交 3557 次通过
题目描述
There is an N*M matrix with only 0s and 1s, (1 <= N,M <= 1000). An exact cover is a selection of rows such that every column has a 1 in exactly one of the selected rows. Try to find out the selected rows.
输入
There are multiply test cases. First line: two integers N, M; The following N lines: Every line first comes an integer C(1 <= C <= 100), represents the number of 1s in this row, then comes C integers: the index of the columns whose value is 1 in this row.
输出
First output the number of rows in the selection, then output the index of the selected rows. If there are multiply selections, you should just output any of them. If there are no selection, just output "NO".
样例输入
6 7
3 1 4 7
2 1 4
3 4 5 7
3 3 5 6
4 2 3 6 7
2 2 7
样例输出
3 2 4 6
提示
来源
dupeng


DancingLinkX算法的模板题

题意给一个矩阵N*M

给你第i行1的个数和位置

让你选一些行精确覆盖M列(精确覆盖:每列有且只有1个1)

如果有解随意输出一组

否则输出NO


#include 
#include 
#include 

const int MN=1005;
const int MM=1005;
const int MNN=1e5+5+MM; //最大点数

struct DLX
{
    int n,m,si;//n行数m列数si目前有的节点数
    //十字链表组成部分
    int U[MNN],D[MNN],L[MNN],R[MNN],Row[MNN],Col[MNN];
    //第i个结点的U向上指针D下L左R右,所在位置Row行Col列
    int H[MN],S[MM]; //记录行的选择情况和列的覆盖情况
    int ansd,ans[MN];
    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;         //横向的连起来
        }
        R[m]=0;L[0]=m;
        si=m;                 //目前用了前0~m个结点
        for(int i=1;i<=n;i++)
            H[i]=-1;
    }
    void link(int r,int c)    //插入点(r,c)
    {
        ++S[Col[++si]=c];     //si++;Col[si]=c;S[c]++;
        Row[si]=r;
        D[si]=D[c];
        U[D[c]]=si;
        U[si]=c;
        D[c]=si;
        if(H[r]<0)
            H[r]=L[si]=R[si]=si;
        else
        {
            R[si]=R[H[r]];
            L[R[H[r]]]=si;
            L[si]=H[r];
            R[H[r]]=si;
        }
    }
    void remove(int c)        //列表中删掉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)        //恢复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) //选取了d行
    {
        if(R[0]==0)//全部覆盖了
        {
            //全覆盖了之后的操作
            ansd=d;
            return 1;
        }
        int c=R[0];
        for(int i=R[0];i!=0;i=R[i])
            if(S[i]


你可能感兴趣的:(其他OJ,DancingLinksX)