2018.08.02 洛谷P3355 骑士共存问题(最小割)

时间:2021-12-04 19:55:52

传送门

这题让我联想到一道叫做方格取数问题的题,如果想使摆的更多,就要使不能摆的更少,因此根据骑士的限制条件建图,求出至少有多少骑士不能摆,减一减就行了。

代码:

#include<bits/stdc++.h>
using namespace std;
int n,m,tot=0,d[500005],dx[8]={1,1,-1,-1,2,2,-2,-2},dy[8]={2,-2,2,-2,1,-1,1,-1},s,t,cnt=-1,first[500005],tim[205][205];
bool f[205][205];
struct Node{int v,next,c;}e[500005];
inline void add(int u,int v,int c){e[++cnt].v=v,e[cnt].next=first[u],e[cnt].c=c;first[u]=cnt;}
inline bool bfs(){
    queue<int>q;
    memset(d,-1,sizeof(d));
    q.push(s),d[s]=0;
    while(!q.empty()){
        int x=q.front();
        q.pop();
        for(int i=first[x];~i;i=e[i].next){
            int v=e[i].v;
            if(e[i].c<=0||d[v]!=-1)continue;
            d[v]=d[x]+1;
            if(v==t)return true;
            q.push(v);
        }
    }
    return false;
}
inline int dfs(int x,int f){
    if(!f||x==t)return f;
    int flow=f;
    for(int i=first[x];~i;i=e[i].next){
        int v=e[i].v;
        if(d[v]!=d[x]+1||e[i].c<=0||!flow)continue;
        int tmp=dfs(v,min(flow,e[i].c));
        if(!tmp)d[v]=-1;
        e[i].c-=tmp;
        e[i^1].c+=tmp;
        flow-=tmp;
    }
    return f-flow;
}
int main(){
    memset(f,false,sizeof(f));
    memset(first,-1,sizeof(first));
    scanf("%d%d",&n,&m),s=0,t=n*n+1;
    for(int i=1;i<=m;++i){
        int x,y;
        scanf("%d%d",&x,&y);
        f[x][y]=true;
    }
    for(int i=1;i<=n;++i)
        for(int j=1;j<=n;++j)
            tim[i][j]=++tot;
    for(int i=1;i<=n;++i)
        for(int j=1;j<=n;++j){
            if(f[i][j])continue;
            if((i+j)&1){
                add(s,tim[i][j],1),add(tim[i][j],s,0);
                for(int k=0;k<8;++k){
                    int mx=dx[k]+i,my=dy[k]+j;
                    if(f[mx][my])continue;
                    if(mx>=1&&my>=1&&mx<=n&&my<=n)
                        add(tim[i][j],tim[mx][my],0x3f3f3f3f),add(tim[mx][my],tim[i][j],0);
                }
            }
            else add(tim[i][j],t,1),add(t,tim[i][j],0);
        }
    int ans=0;
    while(bfs())ans+=dfs(s,0x3f3f3f3f);
    printf("%d",n*n-ans-m);
    return 0;
}