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(); }