KarmaticEnding @ 2024-09-30 11:49:43
关于本题,我的思路是网络流最大流实现二分图,但是第三个点显示
#include<bits/stdc++.h>
using namespace std;
const int MAXN=1e5+10,MAXM=4e5+10;
const int s=1e5+8,t=1e5+9,INF=1e5;
int dis[MAXN],cur[MAXN];
queue<int> q;
int h[MAXN],e[MAXM],c[MAXM],nxt[MAXM],idx=0;
int ans=0;
int n,m;
bool isobs[256][256];//是障碍
const int p[8][2]={{-2,-1},{-2,1},{-1,-2},{-1,2},{2,-1},{2,1},{1,-2},{1,2}};
inline int pos(int x,int y){
return (x-1)*n+y;
}
inline void add(int u,int v,int _c){
e[idx]=v;
c[idx]=_c;
nxt[idx]=h[u];
h[u]=idx;
++idx;
}
bool BFS(){
while(q.size()){
q.pop();
}
memset(dis,-1,sizeof(dis));
dis[s]=0;
q.push(s);
cur[s]=h[s];
while(q.size()){
int u=q.front();
q.pop();
for(int i=h[u];~i;i=nxt[i]){
int v=e[i];
if(dis[v]==-1&&c[i]>0){
dis[v]=dis[u]+1;
q.push(v);
cur[v]=h[v];
if(v==t){
return true;
}
}
}
}
return false;
}
int _find_(int u,int limit){
if(u==t){
return limit;
}
int flow=0;
for(int i=cur[u];~i;i=nxt[i]){
cur[u]=i;
int v=e[i];
if(dis[v]==dis[u]+1&&c[i]>0){
int tf=_find_(v,min(c[i],limit-flow));
if(tf==0){
dis[v]=-1;
}
c[i]-=tf;
c[i^1]+=tf;
flow+=tf;
}
}
return flow;
}
int Dinic(){
int res=0,flow;
while(BFS()){
flow=_find_(s,INF);
while(flow){
res+=flow;
flow=_find_(s,INF);
}
}
return res;
}
int main(){
memset(h,-1,sizeof(h));
scanf("%d%d",&n,&m);//n×n,m个障碍
ans=n*n;
for(int i=1,x,y;i<=m;++i){
scanf("%d%d",&x,&y);
isobs[x][y]=true;
--ans;
}
for(int i=1;i<=n;++i){
for(int j=1;j<=n;++j){
if(isobs[i][j]){
continue;
}
if((i+j)&1){
// printf("(%d,%d):left\n",i,j);
add(s,pos(i,j),1);
add(pos(i,j),s,0);
}
else{
// printf("(%d,%d):right\n",i,j);
add(pos(i,j),t,1);
add(t,pos(i,j),0);
}
}
}
for(int i=1;i<=n;++i){
for(int j=1;j<=n;++j){
if(((i+j)&1)&&(!isobs[i][j])){
for(int k=0;k<8;++k){
int x=i+p[k][0],y=j+p[k][1];
if(x<=0||y<=0||x>n||y>n||isobs[x][y]){
continue;
}
add(pos(i,j),pos(x,y),1);
add(pos(x,y),pos(i,j),0);
// printf("(%d,%d)->(%d,%d)\n",i,j,x,y);
}
}
}
}
printf("%d",ans-Dinic());
return 0;
}