舞蹈链
解决精确覆盖问题
精确覆盖问题:在一个全集中若干子集的集合为,精确覆盖是指,的子集,满足中的每一个元素在中恰好出现一次。在计算机科学中,精确覆盖问题指找出这样的一种覆盖,或证明其不存在。
对于重复覆盖问题,感觉跟深搜差不多,甚至玄学剪枝后深搜会更快,所以不去探索舞蹈链写法了。
代码,详细解释看注释:
点击查看代码
#include<bits/stdc++.h>
#define int long long
#define inf 1e18
#define inc 0xcfcfcfcf
#define N 507
#define M 500007
#define mod 1000000007
//#pragma GCC optimize(2)
//#pragma GCC optimize(3)
using namespace std;
int T=1,n,m,head,lcnt;
int l[N*N],r[N*N],u[N*N],d[N*N],row[N*N],col[N*N],num[N];
vector<int> g[N];
void Init()//生成每列头结点
{
for(int i=0;i<=m;++i)
{
u[i]=d[i]=i;
l[i]=i-1;
r[i]=i+1;
}
l[head]=m;//辅助结点左右相连
r[m]=head;
lcnt=m+1;
}
void Addrow(int x)//加入第x行
{
int first=lcnt;//记录行初始的那个点
for(int i=0;i<g[x].size();++i)
{
int j=g[x][i];
u[lcnt]=u[j];
d[u[j]]=lcnt;
u[j]=lcnt;
d[lcnt]=j;
l[lcnt]=lcnt-1;//先直接连接,后面再处理左右两头
r[lcnt]=lcnt+1;
col[lcnt]=j;
row[lcnt]=x;
++num[j];
++lcnt;
}
l[first]=lcnt-1;//左右两头修改
r[lcnt-1]=first;
}
void Remove(int x)//删除第x列并且将该列上有1的行与上下行脱离
{
r[l[x]]=r[x];
l[r[x]]=l[x];
for(int i=d[x];i!=x;i=d[i])
for(int j=r[i];j!=i;j=r[j])//因为j!=i,所以该列上下仍然相连,因此可以恢复
{
u[d[j]]=u[j];
d[u[j]]=d[j];
--num[col[j]];
}
}
void Resume(int x) //恢复同理
{
for(int i=u[x];i!=x;i=u[i])
for(int j=l[i];j!=i;j=l[j])
{
d[u[j]]=j;
u[d[j]]=j;
++num[col[j]];
}
r[l[x]]=x;
l[r[x]]=x;
}
bool Dance(int dep)
{
if(r[head]==head)
return 1;
int now=r[head];
for(int i=now;i!=head;i=r[i])//剪枝,找点数少的列准备删除
if(num[i]<num[now])
now=i;
Remove(now);
for(int i=d[now];i!=now;i=d[i])
{
for(int j=r[i];j!=i;j=r[j])//删除该列上有1的行所在的所有列
Remove(col[j]);
if(Dance(dep+1))
{
printf("%lld ",row[i]);
return 1;
}
for(int j=l[i];j!=i;j=l[j])
Resume(col[j]);
}
Resume(now);
return 0;
}
bool Solve()
{
//freopen("test.in","r",stdin);
scanf("%lld%lld",&n,&m);
Init();
for(int i=1;i<=n;++i)
{
for(int j=1;j<=m;++j)
{
int in;
scanf("%lld",&in);
if(in)
g[i].push_back(j);
}
Addrow(i);
}
if(!Dance(1))
printf("No solution!");
printf("\n");
return true;
}
signed main()
{
//scanf("%lld",&T);
while(T--)
if(!Solve())
printf("-1\n");
return 0;
}
/*
-std=c++11
-std=c99
*/
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】