LUOGU P3355 骑士共存问题(二分图最大独立集)

传送门

因为骑士只能走"日"字,所以一定是从一个奇点到偶点或偶点到奇点,那么这就是一张二分图,题目要求的其实就是二分图的最大独立集。最大独立集=n-最大匹配。

#include<iostream>
#include<cstdio>
#include<cstring>

using namespace std;
const int MAXN = 205*205;
//const int MAXM = 205*205;
const int MAXM = 8*MAXN;

inline int rd(){
    int x=0,f=1;char ch=getchar();
    while(!isdigit(ch)) {f=ch=='-'?0:1;ch=getchar();}
    while(isdigit(ch))  {x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
    return f?x:-x;
}

int xx[8]={2,1,-1,-2,-2,-1,1,2},yy[8]={1,2,2,1,-1,-2,-2,-1};
int n,m,head[MAXN],cnt,vis[MAXN],match[MAXN];
int to[MAXM<<1],nxt[MAXM<<1],num,ans;
bool ban[205][205];

inline void add(int bg,int ed){
//    cout<<bg<<" "<<ed<<endl;
    to[++cnt]=ed,nxt[cnt]=head[bg],head[bg]=cnt;
}

inline void bfs(int x,int y){
    for(register int i=0;i<=7;i++){
        int ii=xx[i]+x,jj=yy[i]+y;
        if(ii<1 || ii>n || jj<1 || jj>n || ban[ii][jj]) continue;
        add((x-1)*n+y,(ii-1)*n+jj);
    }
}

bool dfs(int x){
    for(register int i=head[x];i;i=nxt[i]){
        int u=to[i];if(vis[u]==num) continue;
        vis[u]=num;
        if(!match[u] || dfs(match[u])) {match[u]=x;return true;} 
    }
    return false;
}

int main(){
    n=rd(),m=rd();int x,y;
    for(register int i=1;i<=m;i++){
        x=rd(),y=rd();
        ban[x][y]=1;
    }
    for(register int i=1;i<=n;i++)
        for(register int j=(1+((i-1)&1));j<=n;j+=2)
            if(!ban[i][j]) bfs(i,j);
    for(register int i=1;i<=n;i++)
        for(register int j=(1+((i-1)&1));j<=n;j+=2)
            if(!ban[i][j]) num++,ans+=dfs((i-1)*n+j);
    cout<<(n*n-m)-ans;
    return 0;
}
View Code
原文地址:https://www.cnblogs.com/sdfzsyq/p/9754391.html