hust1017 Exact cover :DLX精准覆盖模板题

题目链接:http://acm.hust.edu.cn/problem/show/1017

上个星期在空闲时间看了一下DLX博客http://www.cnblogs.com/grenet/p/3145800.html

然后今天昨天学习了bin巨的DLX模板,关于模板的个人理解代码已标出,下面开始做几道DLX==

 1 #include<stdio.h>
 2 #include<string.h>
 3 #include<algorithm>
 4 using namespace std;
 5 struct DLX{
 6   int n,m,size,ansd,ans[1005];
 7   int U[100005],D[100005],L[100005],R[100005];
 8   int Row[100005],Col[100005],H[1005],S[1005];
 9   //H表示该行最右点,S表示该列点数
10   //head在原点,在坐标轴第二象限的DLX
11   void init(int _n,int _m){
12     n=_n; m=_m;
13     for (int i=0;i<=m;i++){
14       S[i]=0;
15       U[i]=D[i]=i;
16       L[i]=i-1; R[i]=i+1;
17     }
18     R[m]=0; L[0]=m;
19     size=m;
20     for (int i=1;i<=n;i++) H[i]=-1;
21   }
22   void link(int r,int c){
23     S[c]++;
24     Col[++size]=c; Row[size]=r;
25     D[size]=D[c]; U[D[c]]=size;
26     U[size]=c; D[c]=size;
27     if (H[r]<0) H[r]=L[size]=R[size]=size;
28     else{
29       R[size]=R[H[r]];
30       L[R[H[r]]]=size;
31       L[size]=H[r];
32       R[H[r]]=size;
33     }
34   }
35   void remove(int c){
36     L[R[c]]=L[c]; R[L[c]]=R[c];
37     for (int i=D[c];i!=c;i=D[i])
38       for (int j=R[i];j!=i;j=R[j]){
39         U[D[j]]=U[j];
40         D[U[j]]=D[j];
41         S[Col[j]]--;
42       }
43   }
44   void resume(int c){
45     for (int i=U[c];i!=c;i=U[i])
46       for (int j=L[i];j!=i;j=L[j]){
47         U[D[j]]=D[U[j]]=j;
48         S[Col[j]]++;
49       }
50     L[R[c]]=R[L[c]]=c;
51   }
52   int dance(int d){
53     if (R[0]==0){
54       ansd=d;
55       return 1;
56     }
57     int c=R[0];
58     for (int i=R[0];i;i=R[i])
59       if (S[i]<S[c]) c=i;
60     remove(c);
61     for (int i=D[c];i!=c;i=D[i]){
62       ans[d]=Row[i];
63       for (int j=R[i];j!=i;j=R[j]) remove(Col[j]);
64       if (dance(d+1)) return 1;
65       for (int j=L[i];j!=i;j=L[j]) resume(Col[j]);
66     }
67     resume(c);
68     return 0;
69   }
70 };
71 DLX g;
72 int main()
73 {
74   int n,m,x,y;
75   while (~scanf("%d%d",&n,&m)){
76     g.init(n,m);
77     for (int i=1;i<=n;i++){
78       scanf("%d",&x);
79       while (x--){
80         scanf("%d",&y);
81         g.link(i,y);
82       }
83     }
84     if (!g.dance(0)) printf("NO\n");
85     else{
86       printf("%d ",g.ansd);
87       for (int i=0;i<g.ansd;i++)
88         printf(" %d",g.ans[i]);
89       printf("\n");
90     }
91   }
92   return 0;
93 }

转载于:https://www.cnblogs.com/xiao-xin/articles/4409364.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值