BZOJ-3175: [Tjoi2013]攻击装置

[文章目录]

Description

给定一个01矩阵,其中你可以在0的位置放置攻击装置。每一个攻击装置(x,y)都可以按照“日”字攻击其周围的 8个位置(x-1,y-2),(x-2,y-1),(x+1,y-2),(x+2,y-1),(x-1,y+2),(x-2,y+1), (x+1,y+2),(x+2,y+1)求在装置互不攻击的情况下,最多可以放置多少个装置。N<=200

黑白染色,求二分图最大点独立集,总点数-最大匹配即可。

#include <queue>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int inf=0x3f3f3f3f;
int s,t,ans,n,m,map[210][210];
int dx[]={-1,-2,-2,-1,1,2,2,1},dy[]={-2,-1,1,2,2,1,-1,-2};
int head[41000],to[401000],nxt[401000],f[401000],cnt=1;
inline void add(int x,int y,int z)
{
    to[++cnt]=y; nxt[cnt]=head[x]; head[x]=cnt; f[cnt]=z;
    to[++cnt]=x; nxt[cnt]=head[y]; head[y]=cnt; f[cnt]=0;
}
queue<int>q;
int dis[41000];
bool bfs()
{
    while(!q.empty()) q.pop();
    memset(dis,-1,sizeof dis);
    dis[s]=0; q.push(s); int x;
    while(!q.empty())
    {
        x=q.front(); q.pop();
        for(int i=head[x];i;i=nxt[i]) if(f[i]>0&&dis[to[i]]==-1)
        {
            dis[to[i]]=dis[x]+1;
            if(to[i]==t) return true;
            q.push(to[i]);
        }
    }
    return false;
}
int dinic(int x,int flow)
{
    if(x==t) return flow;
    int xx,tmp=flow;
    for(int i=head[x];i;i=nxt[i]) if(f[i]>0&&dis[to[i]]==dis[x]+1)
    {
        xx=dinic(to[i],min(f[i],tmp));
        if(!xx) dis[to[i]]=-1;
        f[i]-=xx; f[i^1]+=xx; tmp-=xx;
        if(!tmp) return flow;
    }
    return flow-tmp;
}
int main()
{
    scanf("%d",&n); m=n; s=n*m+1; t=s+1;
    char st[230];
    for(int i=1;i<=n;++i)
    {
        scanf("%s",st+1);
        for(int j=1;j<=m;++j)
            map[i][j]=st[j]=='1';
    }
    int x,y;
    for(int i=1;i<=n;++i)
        for(int j=1;j<=m;++j) if(!map[i][j])
        {
            ans++;
            if((i+j)&1) add(s,(i-1)*m+j,1);
            else add((i-1)*m+j,t,1);
            if((i+j)&1)
                for(int k=0;k<8;++k)
                {
                    x=i+dx[k]; y=j+dy[k];
                    if(x>=1&&x<=n&&y>=1&&y<=m&&!map[x][y])
                        add((i-1)*m+j,(x-1)*m+y,1);
                }
        }
    while(bfs()) ans-=dinic(s,inf);
    printf("%d",ans);
    return 0;
}

发表评论

邮箱地址不会被公开。 必填项已用*标注