HUST 1017 Exact cover(舞蹈链 入门题)(模板记录)

    xiaoxiao2025-02-17  13

    【题意】不解释了,就是裸的DLX模板题,先记录一下DLX的板子,看了半天总算理解了一些。

    【DLX学习】参考这篇博客:点击打开链接 写得非常清楚,顺便赞一句,DLX真的是太神奇了。orz。

    【AC 代码 DLX 模板】

    /********************/ //Created by just_sort 2016/8/13 //All Rights Reserved. //Dancing Links HUST 1017 /********************/ #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> using namespace std; const int maxnode = 100010; const int maxm = 1010; const int maxn = 1010; struct DLX{ int n,m,size; int U[maxnode],D[maxnode],L[maxnode],R[maxnode],Row[maxnode],Col[maxnode]; //U D R L用来记录某个标号的节点的上下左右节点的编号 //Row Col用来记录某个标号的节点在矩阵中的行号和列号 int H[maxn],S[maxm]; //H是行头,S用来保存某一列中1的数量 int ansd,ans[maxn]; 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; 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; } } //对某一列进行删除,并删除列中为1的行 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]){ U[D[j]]=D[U[j]]=j; ++S[Col[j]]; } L[R[c]]=R[L[c]]=c; } //d为递归深度 bool dance(int d) { if(R[0]==0){ ansd=d; return true; } int c=R[0]; //一个优化 找到列中包含1最多的列 因为这样有助于减少递归深度(很显然1多了 删掉的行也多 矩阵缩小得就快) 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]){ ans[d]=Row[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; } }dlx; int main() { int n,m; while(scanf("%d%d",&n,&m)!=EOF) { dlx.init(n,m); for(int i=1; i<=n; i++){ int num,j; scanf("%d",&num); while(num--){ scanf("%d",&j); dlx.Link(i,j); } } if(!dlx.dance(0)) printf("NO\n"); else{ printf("%d",dlx.ansd); for(int i=0; i<dlx.ansd; i++){ printf(" %d",dlx.ans[i]); } printf("\n"); } } return 0; }

    转载请注明原文地址: https://ju.6miu.com/read-1296533.html
    最新回复(0)