bzoj 3175: [Tjoi2013]攻击装置 最大独立集 网络流

来源:互联网 发布:河朔三镇 知乎 编辑:程序博客网 时间:2024/05/14 16:59

题目

传送门

分析

先把整个矩形进行黑白染色,然后就会发现黑的格子只能攻击到白的,白的只能攻击到黑的,那么我们就把格子按照颜色分为二分图,然后连边,那么问题就变成了求最大独立集。
根据最大独立集=点数-最大匹配
直接上dinic

用十分钟就打完了并且1A,真高兴啊。走起,回去睡觉!

代码

#include<iostream>#include<cstdio>#include<cstdlib>#include<cstring>#include<algorithm>#include<queue>#define N 205#define inf 0x3f3f3f3fusing namespace std;int cnt,n,ans,dis[N*N],last[N*N],cur[N*N],map[N][N],s,t,dx[8]={1,2,1,2,-1,-2,-1,-2},dy[8]={2,1,-2,-1,2,1,-2,-1};char ch[N];struct edge{int to,c,next,op;}e[N*1000];queue <int> q;void addedge(int u,int v,int c){    e[++cnt].to=v;e[cnt].c=c;e[cnt].op=cnt+1;e[cnt].next=last[u];last[u]=cnt;    e[++cnt].to=u;e[cnt].c=0;e[cnt].op=cnt-1;e[cnt].next=last[v];last[v]=cnt;}bool bfs(){    for (int i=s;i<=t;i++)        dis[i]=0;    dis[s]=1;    while (!q.empty()) q.pop();    q.push(s);    while (!q.empty())    {        int u=q.front();        q.pop();        for (int i=last[u];i;i=e[i].next)            if (e[i].c&&!dis[e[i].to])            {                dis[e[i].to]=dis[u]+1;                if (e[i].to==t) return 1;                q.push(e[i].to);            }    }    return 0;}int dfs(int x,int maxf){    if (x==t||maxf==0) return maxf;    int ret=0;    for (int &i=cur[x];i;i=e[i].next)        if (e[i].c&&dis[e[i].to]==dis[x]+1)        {            int f=dfs(e[i].to,min(maxf-ret,e[i].c));            e[i].c-=f;            e[e[i].op].c+=f;            ret+=f;            if (ret==maxf) break;        }    return ret;}void dinic(){    while (bfs())    {        for (int i=s;i<=t;i++)            cur[i]=last[i];        ans+=dfs(s,inf);    }}int main(){    scanf("%d",&n);    int sum=n*n;    for (int i=1;i<=n;i++)    {        scanf("%s",ch);        for (int j=1;j<=n;j++)            if (ch[j-1]=='1')             {                map[i][j]=1;                sum--;            }    }    s=0;t=n*n+1;    for (int i=1;i<=n;i++)        for (int j=1;j<=n;j++)            if ((i%2==1&&j%2==1||i%2==0&&j%2==0)&&!map[i][j])            {                addedge(s,(i-1)*n+j,1);                for (int k=0;k<8;k++)                {                    int p=i+dx[k],q=j+dy[k];                    if (p>=1&&p<=n&&q>=1&&q<=n&&!map[p][q]) addedge((i-1)*n+j,(p-1)*n+q,1);                }            }            else if (!map[i][j]) addedge((i-1)*n+j,t,1);    dinic();    printf("%d",sum-ans);    return 0;}
0 0