前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >HUST 1017 Exact cover(DLX精确覆盖)

HUST 1017 Exact cover(DLX精确覆盖)

作者头像
Ch_Zaqdt
发布2019-01-10 16:20:58
6170
发布2019-01-10 16:20:58
举报
文章被收录于专栏:Zaqdt_ACMZaqdt_ACM

       题意是给了n*m的01矩阵,选择最少的行,使得每一列都恰好包含一个1,然后输出这些行


AC代码:

代码语言:javascript
复制
#include <bits/stdc++.h>
using namespace std;
const int maxn = 110;
const int maxm = 110;
const int maxnode = 110 * 110;
int L[maxnode], R[maxnode], U[maxnode], D[maxnode];
int C[maxnode],H[maxn],cnt[maxm],vis[maxn],ans[maxn],Row[maxnode];
int n,m,id,len;

void init(){
    for(int i=0;i<=m;i++){
        cnt[i] = 0; U[i] = D[i] = i;
        L[i + 1] = i; R[i] = i + 1;
    }
    R[m] = 0; id = m + 1;
    memset(H, -1, sizeof(H));
}

void Link(int r, int c){
    cnt[c]++; C[id] = c; Row[id] = r;
    U[id] = U[c]; D[ U[c] ] = id;
    D[id] = c; U[c] = id; Row[id] = r;
    if(H[r] == -1) H[r] = L[id] = R[id] = id;
    else{
        L[id] = L[ H[r] ]; R[ L[ H[r] ] ] = id;
        R[id] = H[r]; L[ H[ r ] ] = id;
    }
    id++;
}

void Remove(int Size){
    L[ R[Size] ] = L[Size];
    R[ L[Size] ] = R[Size];
    for(int i=D[Size];i!=Size;i=D[i]){
        for(int j=R[i];j!=i;j=R[j]){
            U[ D[j] ] = U[j]; D[ U[j] ] = D[j];
            cnt[ C[j] ]--;
        }
    }
}

void Resume(int Size){
    for(int i=D[Size];i!=Size;i=D[i]){
        for(int j=R[i];j!=i;j=R[j]){
            U[ D[j] ] = j; D[ U[j] ] = j;
            cnt[ C[j] ]++;
        }
    }
    L[ R[Size] ] = Size;R[ L[Size] ] = Size;
}

bool DLX(int k){
    int pos,mm = maxn;
    if(R[0] == 0){
        len = k;
        return true;
    }
    for(int i=R[0];i;i=R[i]){
        if(mm > cnt[i]){
            mm = cnt[i];
						pos = i;
        }
    }
    Remove(pos);
    for(int i=D[pos];i!=pos;i=D[i]){
        ans[k] = Row[i];
        for(int j=R[i];j!=i;j=R[j]) Remove(C[j]);
        if(DLX(k + 1)) return true;
        for(int j=L[i];j!=i;j=L[j]) Resume(C[j]);
    }
    Resume(pos);
    return false;
}

int main(){
  int u,v,a;
  while(~scanf("%d%d",&n,&m)){
    init();
    for(int i=1;i<=n;i++){
      int xx;
			scanf("%d",&xx);
			for(int j=1;j<=xx;j++){
				int yy;
				scanf("%d",&yy);
				Link(i, yy);
			}
    }
    bool ans1 = DLX(0);
    if(ans1 == false) printf("No\n");
    else{
			printf("%d",len);
			for(int i=0;i<len;i++){
				printf(" %d",ans[i]);
			}
			puts("");
		}
  }
    return 0;
}
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2018年12月07日,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档