本题和方格取数一样,也可以分成黑白点,本题加上特判一个点是否有障碍即可,其余和那题没什么区别,挂一下大佬的证明(二分图最大独立集)
#include<bits/stdc++.h> using namespace std; #define lowbit(x) ((x)&(-x)) typedef long long LL; const int maxm = 1e6+5; const int INF = 0x3f3f3f3f; const int dx[] = {-2,-2,-1,-1,1,1,2,2}; const int dy[] = {-1,1,-2,2,2,-2,1,-1}; struct edge{ int u, v, cap, flow, nex; } edges[maxm]; int head[maxm], cur[maxm], cnt, level[40005], num[205][205], ID; bool block[205][205]; void init() { memset(head, -1, sizeof(head)); } void add(int u, int v, int cap) { edges[cnt] = edge{u, v, cap, 0, head[u]}; head[u] = cnt++; } void addedge(int u, int v, int cap) { add(u, v, cap), add(v, u, 0); } void bfs(int s) { memset(level, -1, sizeof(level)); queue<int> q; level[s] = 0; q.push(s); while(!q.empty()) { int u = q.front(); q.pop(); for(int i = head[u]; i != -1; i = edges[i].nex) { edge& now = edges[i]; if(now.cap > now.flow && level[now.v] < 0) { level[now.v] = level[u] + 1; q.push(now.v); } } } } int dfs(int u, int t, int f) { if(u == t) return f; for(int& i = cur[u]; i != -1; i = edges[i].nex) { edge& now = edges[i]; if(now.cap > now.flow && level[u] < level[now.v]) { int d = dfs(now.v, t, min(f, now.cap - now.flow)); if(d > 0) { now.flow += d; edges[i^1].flow -= d; return d; } } } return 0; } int dinic(int s, int t) { int maxflow = 0; for(;;) { bfs(s); if(level[t] < 0) break; memcpy(cur, head, sizeof(head)); int f; while((f = dfs(s, t, INF)) > 0) maxflow += f; } return maxflow; } void run_case() { int m, n; LL sum = 0; init(); cin >> n >> m; int s = 0, t = n*n+1; sum += n*n; for(int i = 0; i < m; ++i) { int x, y; cin >> x >> y; block[x][y] = true; } for(int i = 1; i <= n; ++i) { for(int j = 1; j <= n; ++j) { num[i][j] = ++ID; if((i+j)%2==1) { if(!block[i][j]) addedge(s, ID, 1); } else { if(!block[i][j])addedge(ID, t, 1); } } } for(int i = 1; i <= n; ++i) for(int j = 1; j <= n; ++j) { if((i+j)%2==0) continue; for(int k = 0; k < 8; ++k) { int nx = i+dx[k], ny = j+dy[k]; if(nx > n || nx < 1 || ny > n || ny < 1) continue; addedge(num[i][j], num[nx][ny], INF); } } sum -= dinic(s, t); cout << sum-m; } int main() { ios::sync_with_stdio(false), cin.tie(0); run_case(); cout.flush(); return 0; }