题意:nxn的棋盘 有m个坏点 求能在棋盘上放多少个马不会互相攻击
题解:这个题仔细想想居然和方格取数是一样的!!!
每个马他能攻击到的地方的坐标 (x+y)奇偶性不一样 于是就黑白染色
s->黑 白->t
按条件连黑->白 跑最小割 = 最大流
感性理解一下 就是先把所有的点都放上 得到最大的收益
然后删掉一些点使得合法 删掉一个黑点 减去黑点的收益 和黑点相连的白点受到的束缚就减少了
如果s和t点能联通的话 表示还有黑点和白点连通 问题就转化为了最小割
#include <bits/stdc++.h> using namespace std; const int INF = 0x3f3f3f3f; int n, m, s, t, cnt, maxflow; int broke[205][205]; struct node { int to, nex, val; }E[400005]; int head[40005]; int cur[40005]; int dx[] = {-1, -1, 1, 1, -2, -2, 2, 2}; int dy[] = {2, -2, 2, -2, 1, -1, 1, -1}; void addedge(int x, int y, int va) { E[++cnt].to = y; E[cnt].nex = head[x]; head[x] = cnt; E[cnt].val = va; E[++cnt].to = x; E[cnt].nex = head[y]; head[y] = cnt; E[cnt].val = 0; } int dep[40005]; int inque[40005]; bool bfs() { for(int i = 0; i <= t; i++) dep[i] = INF, inque[i] = 0, cur[i] = head[i]; queue<int> que; dep[s] = 0; inque[s] = 1; que.push(s); while(!que.empty()) { int u = que.front(); que.pop(); inque[u] = 0; for(int i = head[u]; i; i = E[i].nex) { int v = E[i].to; if(E[i].val > 0 && dep[v] > dep[u] + 1) { dep[v] = dep[u] + 1; if(!inque[v]) { que.push(v); inque[v] = 1; } } } } if(dep[t] != INF) return true; return false; } int vis; int dfs(int x, int flow) { if(x == t) { vis = 1; maxflow += flow; return flow; } int used = 0; int rflow = 0; for(int i = cur[x]; i; i = E[i].nex) { cur[x] = i; int v = E[i].to; if(E[i].val > 0 && dep[v] == dep[x] + 1) { if(rflow = dfs(v, min(flow - used, E[i].val))) { used += rflow; E[i].val -= rflow; E[i ^ 1].val += rflow; if(used == flow) break; } } } return used; } void dinic() { maxflow = 0; while(bfs()) { vis = 1; while(vis) { vis = 0; dfs(s, INF); } } } int id(int x, int y) { return (x - 1) * n + y; } bool check(int x, int y) { if(x >= 1 && x <= n && y >= 1 && y <= n) return true; return false; } int main() { cnt = 1; scanf("%d%d", &n, &m); s = 0; t = n * n + 1; for(int i = 1; i <= m; i++) { int x, y; scanf("%d%d", &x, &y); broke[x][y] = 1; } for(int i = 1; i <= n; i++) { for(int j = 1; j <= n; j++) { int ii = id(i, j); if(broke[i][j]) continue; if((i + j) % 2 != 1) { addedge(s, ii, 1); for(int k = 0; k < 8; k++) { int ax = i + dx[k]; int ay = j + dy[k]; if(check(ax, ay) && !broke[ax][ay]) addedge(ii, id(ax, ay), INF); } } else addedge(ii, t, 1); } } dinic(); printf("%d ", n * n - m - maxflow); return 0; }