codevs 1922 骑士共存问题 网络流
给一个n*n的棋盘, 上面有障碍物, 有障碍物的不能放东西。然后往上面放马, 马不能互相攻击, 问最多可以放多少个马。
按x+y的奇偶来划分, 如果两个格子可以互相攻击, 就连一条权值为1的边。
#include <iostream> #include <vector> #include <cstdio> #include <cstring> #include <algorithm> #include <complex> #include <cmath> #include <map> #include <set> #include <string> #include <queue> #include <stack> #include <bitset> using namespace std; #define pb(x) push_back(x) #define ll long long #define mk(x, y) make_pair(x, y) #define lson l, m, rt<<1 #define mem(a) memset(a, 0, sizeof(a)) #define rson m+1, r, rt<<1|1 #define mem1(a) memset(a, -1, sizeof(a)) #define mem2(a) memset(a, 0x3f, sizeof(a)) #define rep(i, n, a) for(int i = a; i<n; i++) #define fi first #define se second typedef complex <double> cmx; typedef pair<int, int> pll; const double PI = acos(-1.0); const double eps = 1e-8; const int mod = 1e9+7; const int inf = 1061109567; const int dir[][2] = { {-1, 2}, {-1, -2}, {1, 2}, {1, -2}, {2, -1}, {2, 1}, {-2, -1}, {-2, 1} }; const int maxn = 2e5; int n, a[205][201]; int q[maxn*2], head[50004], dis[50004], s, t, num, m; struct node { int to, nextt, c; node(){} node(int to, int nextt, int c):to(to), nextt(nextt), c(c){} }e[maxn*2]; void init() { num = 0; mem1(head); } void add(int u, int v, int c) { e[num] = node(v, head[u], c); head[u] = num++; e[num] = node(u, head[v], 0); head[v] = num++; } int bfs() { mem(dis); dis[s] = 1; int st = 0, ed = 0; q[ed++] = s; while(st<ed) { int u = q[st++]; for(int i = head[u]; ~i; i = e[i].nextt) { int v = e[i].to; if(!dis[v]&&e[i].c) { dis[v] = dis[u]+1; if(v == t) return 1; q[ed++] = v; } } } return 0; } int dfs(int u, int limit) { if(u == t) { return limit; } int cost = 0; for(int i = head[u]; ~i; i = e[i].nextt) { int v = e[i].to; if(e[i].c&&dis[v] == dis[u]+1) { int tmp = dfs(v, min(limit-cost, e[i].c)); if(tmp>0) { e[i].c -= tmp; e[i^1].c += tmp; cost += tmp; if(cost == limit) break; } else { dis[v] = -1; } } } return cost; } int dinic() { int ans = 0; while(bfs()) { ans += dfs(s, inf); } return ans; } int check(int x, int y) { if(x >= 0 && y >= 0 && x < n && y < n && !a[x][y]) return 1; return 0; } void solve() { init(); s = n*n, t = s+1; for(int i = 0; i < n; i++) { for(int j = 0; j < n; j++) { if(a[i][j]) continue; if((i+j)%2) { add(s, i*n+j, 1); for(int k = 0; k < 8; k++) { int x = i+dir[k][0]; int y = j+dir[k][1]; if(check(x, y)) { add(i*n+j, x*n+y, 1); } } } else { add(i*n+j, t, 1); } } } int ans = n*n-dinic()-m; cout<<ans<<endl; } int main() { int x, y; while(~scanf("%d%d", &n, &m)) { mem(a); for(int i = 0; i < m; i++) { scanf("%d%d", &x, &y); x--; y--; a[x][y] = 1; } solve(); } return 0; }