【DLX】 hdu3498 whosyourdaddy

3 篇文章 0 订阅

whosyourdaddy 

题目:http://acm.hdu.edu.cn/showproblem.php?pid=3498

题意:英雄可以放一个技能,使得一个点和与其相邻的点受到伤害,问最少攻击几个点能够让所有的点都受到至少一次伤害。

题解:建模套DLX模板。

代码:

#include<cstdio>
#include<cstring>
#include<climits>
#define N 60
#define M 3600
using namespace std;
struct
{
    int col,row;
} node[M];
int l[M],r[M],d[M],u[M],h[M],res[N],cntcol[N];
int dcnt=-1,minn;
int n,m;
bool visit[N],mark[N][N];
int H()
{
    int count=0;
    bool hash[N];
    memset(hash,false,sizeof(hash));
    for(int i=r[0]; i!=0; i=r[i])
    {
        if(hash[i]) continue;
        //hash[i]=true;
        count++;
        for(int j=d[i]; j!=i; j=d[j])
            for(int k=r[j]; k!=j; k=r[k])
                hash[node[k].col]=true;
    }
    return count;
}
void addnode(int &x)
{
    ++x;
    r[x]=l[x]=u[x]=d[x]=x;
}
void insert_row(int rowx,int x)
{
    r[l[rowx]]=x;
    l[x]=l[rowx];
    r[x]=rowx;
    l[rowx]=x;
}
void insert_col(int colx,int x)
{
    d[u[colx]]=x;
    u[x]=u[colx];
    d[x]=colx;
    u[colx]=x;
}
void dlx_init(int cols)
{
    memset(h,-1,sizeof(h));
    memset(cntcol,0,sizeof(cntcol));
    dcnt=-1;
    addnode(dcnt);
    for(int i=1; i<=cols; ++i)
    {
        addnode(dcnt);
        insert_row(0,dcnt);
    }
}
void insert_node(int x,int y)
{
    //printf("insert %d %d\n",x,y);
    cntcol[y]++;
    addnode(dcnt);
    node[dcnt].row=x;
    node[dcnt].col=y;
    insert_col(y,dcnt);
    if(h[x]==-1) h[x]=dcnt;
    else insert_row(h[x],dcnt);
}
void remove(int c)
{
    for(int i=d[c]; i!=c; i=d[i])
    {
        l[r[i]]=l[i];
        r[l[i]]=r[i];
    }
}
void resume(int c)
{
    for(int i=u[c]; i!=c; i=u[i])
    {
        l[r[i]]=i;
        r[l[i]]=i;
    }
}
void DLX(int deep)
{
    if(deep+H()>=minn) return;
    if(r[0]==0)
    {
        if(minn>deep) minn=deep;
        return;
    }
    int min=INT_MAX,tempc;
    for(int i=r[0]; i!=0; i=r[i])
        if(cntcol[i]<min)
        {
            min=cntcol[i];
            tempc=i;
        }
    for(int i=d[tempc]; i!=tempc; i=d[i])
    {
        if(visit[node[i].row]) continue;
        res[deep]=node[i].row;
        remove(i);
        for(int j=r[i]; j!=i; j=r[j]) remove(j);
        DLX(deep+1);
        for(int j=l[i]; j!=i; j=l[j]) resume(j);
        resume(i);
    }
    return;
}
int main()
{
    int k;
    int a,b;
    for(; ~scanf("%d%d",&n,&m);)
    {
        memset(mark,false,sizeof(mark));
        dlx_init(n);//初始化
        for(; m--;)
        {
            scanf("%d%d",&a,&b);
            mark[a][b]=mark[b][a]=true;
        }
        for(int i=1; i<=n; ++i)
            for(int j=1; j<=n; ++j)
                if(mark[i][j]||i==j)
                    insert_node(i,j);
        minn=INT_MAX;
        DLX(0);
        printf("%d\n",minn);
    }
    return 0;
}

来源: http://blog.csdn.net/ACM_Ted

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值