【bzoj3175】[Tjoi2013]攻击装置

每两个能互相攻击且能放置的点连一条双向边,然后跑二分图最大点独立集即可

#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<cstdio>
#include<cmath>
using namespace std;
 
typedef long long LL;
 
#define M 80010
#define N 210
 
struct edge
{
    int to,next;
}e[M<<1];
int head[M<<1];
int cnt;
 
int ly[M];
 
int a[N][N],flag[M];
 
char s[N]; 
 
int dx[]={1,1,2,2};
int dy[]={2,-2,1,-1};
 
int n,q;
int tot,ans;
 
void link(int x,int y)
{
    e[++cnt]=(edge){y,head[x]};
    head[x]=cnt;
}
 
bool find(int x)
{
    for (int i=head[x];i;i=e[i].next)
    {
        int t=e[i].to;
        if (flag[t]!=q)
        {
            flag[t]=q;
            if (!ly[t] || find(ly[t]))
            {
                ly[t]=x;
                return true;
            }
        }
    }
    return false;
}
 
int main()
{
    scanf("%d",&n);
    for (int i=1;i<=n;i++)
    {
        scanf("%s",s+1);
        for (int j=1;j<=n;j++)
            if (s[j]=='0')
                a[i][j]=++tot;
            else
                a[i][j]=0;
    }
    for (int i=1;i<=n;i++)
        for (int j=1;j<=n;j++)
            if (a[i][j])
                for (int k=0;k<4;k++)
                {
                    int x=i+dx[k],y=j+dy[k];
                    if (x<1 || x>n || y<1 || y>n)
                        continue;
                    if (a[x][y])
                        link(a[i][j],a[x][y]),link(a[x][y],a[i][j]);
                }
    for (int i=1;i<=tot;i++)
    {
        q++;
        if (find(i))
            ans++;
    }
    printf("%d\n",tot-ans/2);
    return 0;
}

  

posted @ 2016-08-11 15:21  Yangjiyuan  阅读(147)  评论(0编辑  收藏  举报