HUST 1017 舞蹈链之不可重复覆盖

点击打开链接

题意:每一行的某些列给定为1,现在问是否能找某些行,使得每一列的1出现一次

思路:与可重复覆盖的区别就是选定的列的1与其它行的又重复的,那么重复的那行也需要删除,而可重复的不需要删除,那么直接改一改之前的那个模版就可以求这道题了,而且需要输出所选行,任意一个就可以,那么在查找的时候直接赋给一个数组即可

#include <vector>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int inf=0x3f3f3f3f;
const ll INF=0x3f3f3f3f3f3f3f3fll;
const int maxn=1010;
int L[maxn*100],R[maxn*100],U[maxn*100],D[maxn*100];//节点的上下左右四个方向的链表
int C[maxn*100],H[maxn],cnt[maxn],vis[maxn],ans[maxn],Row[maxn*100];//C列H行cnt列链表中元素个数
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;
}
int Dance(int k){
    int pos,mm=maxn;
    if(R[0]==0){
        len=k;
        return 1;
    }
    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(Dance(k+1)) return 1;
        for(int j=L[i];j!=i;j=L[j]) Resume(C[j]);
    }
    Resume(pos);
    return 0;
}
int main(){
    int u,v,a;
    while(scanf("%d%d",&n,&m)!=-1){
        init();
        for(int i=1;i<=n;i++){
            scanf("%d",&a);
            while(a--){
                scanf("%d",&u);
                Link(i,u);
            }
        }
        int flag=Dance(0);
        if(flag==0) printf("NO\n");
        else{
            printf("%d",len);
            for(int i=0;i<len;i++) printf(" %d",ans[i]);
            printf("\n");
        }
    }
    return 0;
}
时间: 2024-10-06 08:05:46

HUST 1017 舞蹈链之不可重复覆盖的相关文章

HDU 3663 舞蹈链之不可重复覆盖

点击打开链接 题意:给一个无向图,然后n个城市的供电范围,每个现在要求每一个城市的D天都可以有电,对于城市A发电,那么与它相邻的所有城市都会有电,但是问题是每个城市一天内只可以被供电一次,否则会坏掉,并且每个城市的供电天数有范围而且每个城市只能开启开关一次,之后不能在使用,也就是说城市A的供电时间必须是连续的,还有就是可以不用这个城市 思路:因为每个城市一天只能被供电一次,那么就是不可重复覆盖的舞蹈链模型了,那么考虑的就是把什么作为列和行了,很明显这道题就是N*D+N作为列,N*D是n个城市的D

HDU 3529 舞蹈链之可重复覆盖

点击打开链接 题意:在点的地方放炸弹,炸弹可以炸到的地方无限远并且是十字的形式,但是如果炸到#或者*则这个方向停下来,问最少需要多少炸弹同时引爆才可以将所有#炸掉 思路:一道模版舞蹈链了,对于建图我们将所有的#看做列,然后所有的点也就是放炸弹的地方看做行,然后找一下每个点可以炸的#就可以了,建图后跑个舞蹈链可重复的模版就可以了 #include <vector> #include <stdio.h> #include <string.h> #include <st

FZU 1686 舞蹈链之可重复覆盖

点击打开链接 题意:中文题了 思路:做了几个舞蹈链的题目了,第一感觉总会想到去用网络流去写,哎YY一会就是错的,乖乖用舞蹈链来写把,对于这道题目我们可以将所有的1看成是列,然后行则是一个一个的小矩阵,每一行也就是小矩阵连接自己可以消灭的1,但是首先要给所有的1编一下号,再然后就是模版舞蹈链了 #include <vector> #include <stdio.h> #include <string.h> #include <stdlib.h> #includ

HDU 2828 舞蹈链可重复覆盖

点击打开链接 题意:给n个灯,每个灯能保持亮的状态的条件给出,最后问能否将所有的灯都保持亮的状态,能的话输出每个开关的状态 思路:明显的舞蹈链可重复覆盖嘛,列为n个灯,然后行为每个开关开还是关,所以行要有2*m行,注意的是在跑舞蹈链的时候,每一个开关只能有开或关的状态,所以我们要判断一下它对应的状态是否走过 #include <vector> #include <stdio.h> #include <string.h> #include <stdlib.h>

HDU 2295 舞蹈链可重复覆盖+二分

点击打开链接 题意:给了n个点和m个圆心,在用不多于k个圆的情况下,使得所有的点被覆盖,最小的圆半径多大 思路:问最小的什么什么那么用二分准没错,那么二分条件是什么呢,就是用不多于K的圆能否将所有点覆盖,覆盖这部分就是裸的舞蹈链的可重复覆盖,行为m个圆,列为n个点,然后求出的最少行小于等于K,则成立,否则不成立 #include <math.h> #include <vector> #include <stdio.h> #include <string.h>

(简单) HUST 1017 Exact cover , DLX+精确覆盖。

Description There is an N*M matrix with only 0s and 1s, (1 <= N,M <= 1000). An exact cover is a selection of rows such that every column has a 1 in exactly one of the selected rows. Try to find out the selected rows. DLX精确覆盖的模板题...... 代码如下: //HUST 1

UVALive 2659+HUST 1017+ZOJ 3209 (DLX

UVALive 2659 题目:16*16的数独.试了一发大白模板. /* * @author: Cwind */ //#pragma comment(linker, "/STACK:102400000,102400000") #include <iostream> #include <map> #include <algorithm> #include <cstdio> #include <cstring> #include

FZU 1686 神龙的难题(重复覆盖问题&amp;舞蹈链)

题目链接:[kuangbin带你飞]专题三 Dancing Links D - 神龙的难题 题意 Description 这是个剑与魔法的世界.英雄和魔物同在,动荡和安定并存.但总的来说,库尔特王国是个安宁的国家,人民安居乐业,魔物也比较少.但是.总有一些魔物不时会进入城市附近,干扰人民的生活.就要有一些人出来守护居民们不被魔物侵害.魔法使艾米莉就是这样的一个人.她骑着她的坐骑,神龙米格拉一起消灭干扰人类生存的魔物,维护王国的安定.艾米莉希望能够在损伤最小的前提下完成任务.每次战斗前,她都用时间

HUST 1017 - Exact cover (Dancing Links 模板题)

1017 - Exact cover 时间限制:15秒 内存限制:128兆 自定评测 5584 次提交 2975 次通过 题目描述 There is an N*M matrix with only 0s and 1s, (1 <= N,M <= 1000). An exact cover is a selection of rows such that every column has a 1 in exactly one of the selected rows. Try to find o