1. 程式人生 > >洛谷 P3355 騎士共存問題 (網路流24題)

洛谷 P3355 騎士共存問題 (網路流24題)

思路: 聽說這題是最大流 / 最小割 (不會啊) 畫個圖可以知道,根據互相能到達的關係建圖,不存在奇環,即這個圖是二分圖。 然後求不能互相攻擊的騎士數量也就是求這張圖的最大獨立集。 所以答案就等於 節點數 - 障礙數 - 最大匹配數。

程式碼:

#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; }