舞蹈链

#include
using namespace std;
const int maxnode = 100010;
const int maxm = 1010;
const int maxn = 1010;
struct DLX{
    int n,m,sizes;//行数,列数,‘1’的总数
    int D[maxnode],U[maxnode],L[maxnode],R[maxnode];//U D R L用来记录某个标号的节点的上下左右节点的编号
    int Row[maxnode],Col[maxnode];//Row Col用来记录某个标号的节点在矩阵中的行号和列号
    int H[maxn],S[maxm];//H是行头,S保存某一列中1的数量
    int ansd,ans[maxn];//ansd是答案行数,ans[maxn]是每行行号
    void init(int _n,int _m){//初始化列头
        n=_n,m=_m;//读出行列数
        for(int i=0; i<=m; i++){
            S[i]=0;//每列‘1’的数量为0
            D[i]=U[i]=i;//i号结点的上下节点编号是i即本身结点编号,因为只有其一个
            L[i]=i-1,R[i]=i+1;//i号结点的左右节点编号是i-1,i+1
        }
        R[m]=0,L[0]=m;//0号点与m号点循环
        sizes=m;//至此前m(还有0号点)个点初始化完成
        for(int i=1; i<=n; i++) H[i]=-1;
    }
    void Link(int r,int c){//连边!第R行,第C列写1
        ++S[Col[++sizes]=c];//总'1'量SIZES加1个,然后第SIZES编号的节点的列是c,该列‘1’数量即S数组+1
        Row[sizes]=r;//此节点行号是r
        U[sizes]=U[c];//本结点的上指针指向表头指的上指针,实即上次本列的最后一个1编号
        D[U[c]]=sizes;//上次本列的最后一个编号的下指针指向本结点
        D[sizes]=c;//本结点的下指针指向表头
        U[c]=sizes;//本列表头上指针指向本结点
        if(H[r]<0)//如果此行未有点,即head指针仍为-1,则此点的head指针及左右指针均指向这个点
            H[r]=L[sizes]=R[sizes]=sizes;
        else{//如果此行已有点
            R[sizes]=R[H[r]];//此点的右指针指向本行头指针的右结点
            L[R[H[r]]]=sizes;//上次本行的最右点的左指针指向本结点(不是该右吗)
            L[sizes]=H[r];//本结点左指针为本行头指针,注意h[r]从未变过,就是本行第一个‘1’的位置
            R[H[r]]=sizes;//行首右指针改为本结点
        }
    }
    void remove(int c){//删除某列!并删除列中为1的行
        L[R[c]]=L[c];R[L[c]]=R[c];//右点左针指左点,左点右针指右点,注意控制的只是表头!!!
        for(int i=U[c]; i!=c; i=U[i])//往下逐行扫,循环回到本行
            for(int j=R[i]; j!=i; j=R[j]){//往右逐列扫,循环回到本列
                D[U[j]]=D[j];//当前j结点上面的结点的下面的结点记为j结点上面的结点,实现删除本结点
                U[D[j]]=U[j];//当前j结点下面的结点的上面的结点记为j结点下面的结点,实现删除本结点
                --S[Col[j]];//本结点所在行的‘1’数量减一
            }
    }
    void resume(int c){//反着恢复某列!并恢复列中为1的行
        for(int i=D[c]; i!=c; i=D[i])//往下走
            for(int j=L[i]; j!=i; j=L[j]){//往左走
                D[U[j]]=U[D[j]]=j;//上面的下针,下面的上针指向本结点
                ++S[Col[j]];//计数加1
            }
        L[R[c]]=R[L[c]]=c;//右面的左针,左面的右针指本列,注意这是表头!!!
    }
    bool dance(int d){//舞蹈一下,可得答案!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]

 

你可能感兴趣的:(ACM笔记-3图流)