zoukankan      html  css  js  c++  java
  • BZOJ3175[Tjoi2013]攻击装置——二分图最大独立集

    题目描述

    给定一个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,表示矩阵大小为N*N。接下来N行每一行一个长度N的01串,表示矩阵。

    输出

    一个整数,表示在装置互不攻击的情况下最多可以放置多少个装置。

    样例输入

    3
    010
    000
    100

    样例输出

    4

    提示

    100%数据 N<=200

      将矩阵黑白染色(就是相邻格子染不同颜色),可以发现每个攻击装置能攻击到的格子和它所在格子染色不同,将源点连向白色格子,黑色格子连向汇点,每个白点连向能攻击到的黑点,跑二分图最大匹配,然后用总格子数-最大匹配-矩阵中1的个数。这个为什么是对的?因为相连的点表示能互相攻击到,去掉二分图最大匹配的边之后剩下的点之间一定不相连就一定不会互相攻击到。同时给这个残留的二分图加上之前任何一个删除的点都会有匹配边,所以这样是最大的。

    #include<cstdio>
    #include<algorithm>
    #include<iostream>
    #include<cstring>
    #include<cmath>
    using namespace std;
    int next[1000001];
    int to[1000001];
    int val[1000001];
    int head[1000001];
    int tot=1;
    int q[100001];
    int n,k;
    int S,T;
    int ans=0;
    int x,y;
    int d[100001];
    char s[1001][1001];
    int c[1001][1001];
    const int dx[]={-2,-1,1,2,2,1,-1,-2};
    const int dy[]={1,2,2,1,-1,-2,-2,-1};
    void add(int x,int y,int v)
    {
        tot++;
        next[tot]=head[x];
        head[x]=tot;
        to[tot]=y;
        val[tot]=v;
        tot++;
        next[tot]=head[y];
        head[y]=tot;
        to[tot]=x;
        val[tot]=0;
    } 
    bool bfs(int S,int T)
    {
        int r=0;
        int l=0;
        memset(q,0,sizeof(q));
        memset(d,-1,sizeof(d));
        q[r++]=S;
        d[S]=0;
        while(l<r)
        {  
            int now=q[l];
            for(int i=head[now];i;i=next[i])
            {
                if(d[to[i]]==-1&&val[i]!=0)
                {
                    d[to[i]]=d[now]+1;
                    q[r++]=to[i];
                }
            }
            l++;
        }
        if(d[T]==-1)
        {
            return false;
        }
        else
        {
            return true;
        }
    }
    int dfs(int x,int flow)
    {
        if(x==T)
        {
            return flow;
        }
        int now_flow;
        int used=0;
        for(int i=head[x];i;i=next[i])
        {
            if(d[to[i]]==d[x]+1&&val[i]!=0)
            {
                now_flow=dfs(to[i],min(flow-used,val[i]));
                val[i]-=now_flow;
                val[i^1]+=now_flow;
                used+=now_flow;
                if(now_flow==flow)
                {
                    return flow;
                }
            }
        }
        if(used==0)
        {
            d[x]=-1;
        }
        return used;
    }
    void dinic()
    {
        while(bfs(S,T)==true)
        {
            ans+=dfs(S,0x3f3f3f);
        }
    }
    int main()
    {
        scanf("%d",&n);
        S=n*n+1;
        T=n*n+2;
        for(int i=1;i<=n;i++)
        {
            scanf("%s",s[i]+1);
        }
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=n;j++)
            {
                if(s[i][j]=='0')
                {
                    c[i][j]=(i-1)*n+j;
                    if((i+j)%2==0)
                    {
                        add(S,c[i][j],1);
                    }
                    else
                    {
                        add(c[i][j],T,1);
                    }
                }
                else
                {
                    k++;
                }
            }
        }
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=n;j++)
            {
                if(s[i][j]!='1'&&(i+j)%2==0)
                {
                    for(int m=0;m<=7;m++)
                    {
                        int fx=dx[m]+i;
                        int fy=dy[m]+j;
                        if(fx>0&&fx<=n&&fy>0&&fy<=n&&c[fx][fy]!=-1)
                        {
                            add(c[i][j],c[fx][fy],0x3f3f3f);
                        } 
                    }
                }
            }
        }
        dinic();
        printf("%d",n*n-k-ans);
    }
  • 相关阅读:
    (树的直径)第九届湘潭市大学生程序设计比赛 H-Highway
    (记忆化DFS)Codeforces Round #413 D-Field expansion
    (树状数组)Codeforces Round #413 C-Fountains
    (几何)LeetCode Weekly Contest 32 D-Erect the Fence
    LeetCode Weekly Contest 32 解题报告
    (贪心)华师大程序设计竞赛 F-丽娃河的狼人传说
    (最短路)AtCoder Beginner Contest 061 D
    Tinkoff Challenge
    Codeforces Round #410 (Div. 2) 解题报告
    (二叉树)UVA
  • 原文地址:https://www.cnblogs.com/Khada-Jhin/p/9301426.html
Copyright © 2011-2022 走看看