网络流24题 骑士共存问题

题目传送门

好久没写博客了……

照这个速度,退役前怕是做不完网络流24题了


和方格取数其实差不多,还是黑白染色,建出图来之后跑匈牙利求最大匹配数就好了

最后答案是 格子数量 减去 障碍数量和最大匹配数

#include <iostream>
#include <cstdio>
#include <cstring>
#define LL long long
using namespace std;
LL read() {
	LL k = 0, f = 1; char c = getchar();
	while(c < '0' || c > '9') {
		if(c == '-') f = -1;
		c = getchar();
	}
	while(c >= '0' && c <= '9')
		k = k * 10 + c - 48, c = getchar();
	return k * f;
}
struct zzz {
	int t, nex;
}e[100010 << 1]; int head[40010], tot;
inline void add(int x, int y) {
	e[++tot].t = y;
	e[tot].nex = head[x];
	head[x] = tot;
}
int n, m, num[210][210];
bool mapp[2010][2010];
int fx[9] = {0, -2, -1, 1, 2, 2, 1, -1, -2},
	fy[9] = {0, 1, 2, 2, 1, -1, -2, -2, -1};
bool vis[40010]; int lin[40010];
bool find(int x) {
	for(int i = head[x]; i; i = e[i].nex) {
		int to = e[i].t;
		if(!vis[to]) {
			vis[to] = 1;
			if(!lin[to] || find(lin[to])) {
				lin[to] = x; return 1;
			}
		}
	}
	return 0;
}
int q[100010], top;
int main() {
	n = read(), m = read();
	for(int i = 1; i <= m; ++i) {
		int x = read(), y = read();
		mapp[x][y] = 1;
	}
	int cnt = 0;
	for(int i = 1; i <= n; ++i)
		for(int j = 1; j <= n; ++j)
			num[i][j] = ++cnt;
	for(int i = 1; i <= n; ++i)
		for(int j = 1; j <= n; ++j) {
			if(mapp[i][j] || !(i+j & 1)) continue;
			q[++top] = num[i][j];
			for(int k = 1; k <= 8; ++k) {
				int x = i + fx[k], y = j + fy[k];
				if(x <= 0 || x > n || y <= 0 || y > n || mapp[x][y]) continue;
				add(num[i][j], num[x][y]);
			}
		}
	int ans = 0;
	for(int i = 1; i <= top; ++i) {
		memset(vis, 0, sizeof(vis));
		ans += find(q[i]);
	}
	
	cout << n * n - ans - m;
	return 0;
}

其实上面的代码在Luogu上会T掉一个点,可能被卡常了吧 (死也不用dinic) ……

双倍经验:TJOI2013攻击装置

posted @ 2019-11-14 11:07  MorsLin  阅读(119)  评论(0编辑  收藏  举报