6801 棋盘覆盖 0x60「图论」例题
描述
给定一个N行N列的棋盘,已知某些格子禁止放置。求最多能往棋盘上放多少块的长度为2、宽度为1的骨牌,骨牌的边界与格线重合(骨牌占用两个格子),并且任意两张骨牌都不重叠。N≤100。
输入格式
第一行为n,t(表示有t个删除的格子)
第二行到t+1行为x,y,分别表示删除格子所在的位置
x为第x行,y为第y列,行列编号从1开始。
输出格式
一个数,即最多能放的骨牌数
样例输入
8 0
样例输出
32
二分图最大匹配版题
#include<iostream>
#include<cstdio>
#define ri register int
#define u int
namespace opt {
inline u in() {
u x(0),f(1);
char s(getchar());
while(s<'0'||s>'9') {
if(s=='-') f=-1;
s=getchar();
}
while(s>='0'&&s<='9') {
x=(x<<1)+(x<<3)+s-'0';
s=getchar();
}
return x*f;
}
}
using opt::in;
#define NN 10005
#define MM 10005*4
#include<cstring>
namespace mainstay {
u N,K;
u h[NN],cnt;
struct node {
u to,next;
} a[MM];
inline void add(const u &x,const u &y) {
a[++cnt].next=h[x],a[cnt].to=y,h[x]=cnt;
}
inline u calc(const u &x,const u &y) {
return ((x-1)*N+y);
}
u vt[NN],mat[NN],b[NN][NN];
u dfs(const u &x) {
for(ri i(h[x]); i; i=a[i].next) {
u _y(a[i].to);
if(!vt[_y]) {
vt[_y]=1;
if(!mat[_y]||dfs(mat[_y])) {
mat[_y]=x;
return 1;
}
}
}
return 0;
}
inline void solve() {
N=in(),K=in();
for(ri i(1); i<=K; ++i) {
u _a(in()),_b(in());
b[_a][_b]=1;
}
for(ri i(1); i<=N; ++i) {
for(ri j(1); j<=N; ++j) {
if(!b[i][j]) {
if(j+1<=N&&!b[i][j+1]) {
add(calc(i,j),calc(i,j+1));
add(calc(i,j+1),calc(i,j));
}
if(i+1<=N&&!b[i+1][j]) {
add(calc(i,j),calc(i+1,j));
add(calc(i+1,j),calc(i,j));
}
}
}
}
u ans(0);
for(ri i(1); i<=N; ++i) {
for(ri j(1); j<=N; ++j) {
std::memset(vt,0,sizeof(vt));
u _x((i-1)*N+j);
if(((i+j)&1)&&dfs(_x)) ++ans;
}
}
printf("%d",ans);
}
}
int main() {
//freopen("x.txt","r",stdin);
std::ios::sync_with_stdio(false);
mainstay::solve();
}