洛谷 P3355 騎士共存問題 (網路流24題)
阿新 • • 發佈:2018-12-09
思路:
聽說這題是最大流 / 最小割 (不會啊)
畫個圖可以知道,根據互相能到達的關係建圖,不存在奇環,即這個圖是二分圖。
然後求不能互相攻擊的騎士數量也就是求這張圖的最大獨立集。
所以答案就等於 節點數 - 障礙數 - 最大匹配數。
程式碼:
#include<bits/stdc++.h>
using namespace std;
#define maxn 200
#define read(x) scanf("%d",&x)
#define write(x) printf("%d",x);
const int m1[10]={0,1,2,2,1,-1,-2,-2,-1 };
const int m2[10]={0,-2,-1,1,2,-2,-1,1,2};
int n,m;
int a[maxn+5][maxn+5];
int cant;
vector<int> g[maxn*maxn+5];
bool use[maxn*maxn+5];
int match[maxn*maxn+5];
void readin() {
read(n),read(m);
for(int i=1;i<=m;i++) {
int x,y;
scanf("%d%d",&x,&y);
a[x][y]=true ;
}
}
int getid(int x,int y) {
return (x-1)*n+y;
}
void makeg() {
for(int i=1;i<=n;i++) {
for(int j=1;j<=n;j++) {
if(a[i][j]) {
cant++;
continue;
}
if((i+j)&1) {
continue;
}
for (int k=1;k<=8;k++) {
int x=i+m1[k],y=j+m2[k];
if(x>n||y>n||x<=0||y<=0||a[x][y]) continue;
g[getid(i,j)].push_back(getid(x,y));
}
}
}
}
bool dfs(int x){
for(int i=0;i<g[x].size();i++) {
int y=g[x][i];
if(use[y]) continue;
use[y]=true;
if(!match[y]||dfs(match[y])) {
match[y]=x;
return true;
}
}
return false;
}
int slv() {
int s=0;
for(int i=1;i<=n*n;i++) {
memset(use,0,sizeof(use));
s+=dfs(i);
}
return s;
}
int main() {
readin();
makeg();
write(n*n-cant-slv());
return 0;
}