题意:在n*m的网格上填马,其攻击范围是±3,±1这种类型,每个格子有个权值,有些格子可以选,有些不能选,求一种字典序最小的,马互不攻击的,权值之和最大的一种方案
明显按行奇偶染色,就变成了二分图上的最大权独立集的问题,这个是个经典模型,然后考虑怎么输方案,按字典序枚举每个位置,如果想让这个位置必须选,那么就是它连向源或汇的边变为oo,使得最小割割不开,则判断其合法性就是看有没有一条到汇(源)点的增广路,也就是一次bfs就可以了,因此判断复杂度也是o((n*m)^2)的。比赛的时候还是黄哥机智的提出了这个idea,否则我就得每次暴力流一遍了。
其实这题烦的不是算法,而是各种情况,譬如至少放一个马,或者是有负数,同时你又必须选它之类的,比赛时写了一遍,之后又re了一遍,改到拍不出错之后,又手构了几种情况才终于过了。
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
const int dx[8]={-1,-3,-3,-1,1,3,3,1};
const int dy[8]={-3,-1,1,3,3,1,-1,-3};
const int oo=1073741819;
using namespace std;
int tail[20000],next[500000],sora[500000];
int flow[1050][1050],col[1050][1050],id[1050][1050],g[2][