hust 1017 dancing links

开始学习dancing links了,01矩阵覆盖,居然搞了一中午+半个下午。


#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <string>
#include <map>
#include <stack>
#include <vector>
#include <set>
#include <queue>
#pragma comment (linker,"/STACK:102400000,102400000")
#define maxn 22
#define MAXN 100005
#define mod 1000007
#define INF 0x3f3f3f3f
#define pi acos(-1.0)
#define eps 1e-6
typedef long long ll;
using namespace std;
#define N 1005
#define M N*N
int U[M],D[M],L[M],R[M];
int ID[M],row[M],S[N],ans[N];
int k_ans;
void remove(int c)
{
	int i,j;
	L[R[c]]=L[c];
	R[L[c]]=R[c];
	for(i=D[c];i!=c;i=D[i]){
		for(j=R[i];j!=i;j=R[j]){
			U[D[j]]=U[j];
			D[U[j]]=D[j];
			S[ID[j]]--;
		}
	}
}
void resume(int c)
{
	int i,j;
	for(i=U[c];i!=c;i=U[i]){
		for(j=L[i];j!=i;j=L[j]){
			U[D[j]]=D[U[j]]=j;
			S[ID[j]]++;
		}
	}
	R[L[c]]=L[R[c]]=c;
}
void init(int n,int m)
{
    memset(S,0,sizeof(S));
    for(int i=1;i<=m;i++)
    {
        U[i]=D[i]=L[i+1]=R[i-1]=i;
    }
    R[m]=0;
}
bool dfs(int k)
{
  //  printf("%d\n",k);
    if(!R[0]) {k_ans=k;return true;}
    int tmp,mins=0x7fffffff;
    for(int i=R[0];i;i=R[i])
    {
        if(S[i]<mins)
        {
            mins=S[i];
            tmp=i;
        }
    }
    remove(tmp);
    for(int i=D[tmp];i!=tmp;i=D[i]) //选row[i]行
    {
        for(int j=R[i];j!=i;j=R[j])
        {
            remove(ID[j]);
        }
        ans[k]=row[i];
        if(dfs(k+1)) return true;
        for(int j=L[i];j!=i;j=L[j])
        {
            resume(ID[j]);
        }
    }
    resume(tmp);
    return false;
}
int main()
{
    int n,m,k,a,top,base;
    while(~scanf("%d%d",&n,&m))
    {
        init(n,m);
        top=m+1;
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&k);
            for(int j=1;j<=k;j++)
            {
                scanf("%d",&a);
                S[a]++;
                ID[top]=a;row[top]=i;

                U[top]=U[a];D[U[a]]=top;    //插入列
                U[a]=top;D[top]=a;

                if(j==1) {L[top]=R[top]=top;base=top;}  //插入行
                else
                {
                    L[top]=L[base];R[L[base]]=top;
                    L[base]=top;R[top]=base;
                }
                top++;
            }
        }
        if(dfs(0))
        {
            printf("%d",k_ans);
            for(int i=0;i<k_ans;i++) printf(" %d",ans[i]);
            puts("");
        }
        else puts("NO");
    }
    return 0;
}


  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

TommyTT

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值