• 【bzoj4808】【马】二分图最大点独立集+简单感性证明


    这里写图片描述
    (上不了p站我要死了,侵权度娘背锅)

    Description
    众所周知,马后炮是中国象棋中很厉害的一招必杀技。”马走日字”。本来,如果在要去的方向有别的棋子挡住(俗称”蹩马腿”),则不允许走过去。为了简化问题,我们不考虑这一点。马跟马显然不能在一起打起来,于是rly在一天再次借来了许多许多的马在棋盘上摆了起来……但这次,他实在没兴趣算方案数了,所以他只想知道在N×M的矩形方格中摆马使其互不吃到的情况下的最多个数。但是,有一个很不幸的消息,rly由于玩得太Happy,质量本来就不好的棋盘被rly弄坏了,不过幸好只是破了其中的一些格子(即不能再放子了),问题还是可以继续解决的。
    Input
    一行,两个正整数N和M。
    接下来N行,每行M个数,要么为0,表示没坏,要么为1,表示坏了。
    N<=200,M<=200
    Output
    一行,输出最多的个数。
    Sample Input
    2 3
    0 1 0
    0 1 0
    Sample Output
    2

    算是一道裸题了吧
    为了二分图练手以及多见一些二分图的性质

    网格图是天然的二分图(当然并不是网格图就一定是二分图的题),将网格交替染色,则发现马的走法一定是从黑到白(或从白到黑)。那么这就是求互不可达的马的数量,即 最大点独立集

    下面来感性证明一下 最大点独立集=点数-最小点覆盖(最大匹配):
    这里写图片描述
    用最少的点覆盖完了所有的边,那么如果我们删去这些属于最大匹配的点(边的一端),则剩下的点就不会和其他点相邻。如果还与别的点相邻,就说明这其实还是一个匹配,那么之前的匹配就不是最大匹配了。

    1A代码(写的好丑):

    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #define ll long long
    using namespace std;
    
    template <typename T>inline void read(T &res){
        T k=1,x=0;char ch=0;
        while(ch<'0'||ch>'9'){if(ch=='-')k=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
        res=x*k;
    }
    
    const int N=205;
    
    int n,m,c[N][N];
    int head[N*N],to[N*N*8],nxt[N*N*8],hh=0;
    int tot=0,cnt=0;
    int bl[N*N];
    bool vis[N*N];
    
    void adde(int a,int b){
        hh++;
        to[hh]=b;
        nxt[hh]=head[a];
        head[a]=hh;
    }
    bool find(int u){
        for(int i=head[u];i;i=nxt[i]){
            int v=to[i];
            if(vis[v]) continue;
            vis[v]=1;
            if(bl[v]==0||find(bl[v])){
                bl[v]=u;
                return true;
            }
        }
        return false;
    }
    int main(){
        read(n),read(m);
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++){
                read(c[i][j]);
                if(!c[i][j]) tot++;
            }
        for(int i=1;i<=n;i++){
            for(int j=i%2?1:2;j<=m;j+=2){
                if(c[i][j]) continue;
                if(i-2>=1&&j-1>=1&&c[i-2][j-1]==0) adde((i-1)*m+j,(i-3)*m+j-1);
                if(i-2>=1&&j+1<=m&&c[i-2][j+1]==0) adde((i-1)*m+j,(i-3)*m+j+1);
                if(i-1>=1&&j-2>=1&&c[i-1][j-2]==0) adde((i-1)*m+j,(i-2)*m+j-2);
                if(i-1>=1&&j+2<=m&&c[i-1][j+2]==0) adde((i-1)*m+j,(i-2)*m+j+2);
                if(i+2<=n&&j-1>=1&&c[i+2][j-1]==0) adde((i-1)*m+j,(i+1)*m+j-1);
                if(i+2<=n&&j+1<=m&&c[i+2][j+1]==0) adde((i-1)*m+j,(i+1)*m+j+1);
                if(i+1<=n&&j-2>=1&&c[i+1][j-2]==0) adde((i-1)*m+j,i*m+j-2);
                if(i+1<=n&&j+2<=m&&c[i+1][j+2]==0) adde((i-1)*m+j,i*m+j+2);
            }
        }
        for(int i=1;i<=n;i++){
            for(int j=i%2?1:2;j<=m;j+=2){
                memset(vis,0,sizeof(vis));
                if(find((i-1)*m+j)) cnt++;
            }
        }
        printf("%d
    ",tot-cnt);
        return 0;
    }
  • 相关阅读:
    AJAX从后台接收的字符串如何与前台字符串比较
    ojdbc6.jar导入maven依赖失败(亲测有效)
    IDEA怎样创建maven项目
    yum下载rpm包以及相关依赖包
    pip离线安装包
    Python的print的底层实现
    django查询集-17
    django的数据库操作-16
    django数据库迁移-15
    django定义模型类-14
  • 原文地址:https://www.cnblogs.com/LinnBlanc/p/7763089.html
Copyright © 2020-2023  润新知