AcWing 372. 棋盤覆蓋
阿新 • • 發佈:2021-07-11
原題連結
考察:二分匹配
思路:
長度為2的骨牌,相當於骨牌所佔用兩個點匹配,不重疊:沒有一個點共用兩條邊,求能放的骨牌:最大匹配數.
二分匹配前一定要先判斷二分圖,再將點分成兩派,只列舉其中一派.
Code
#include <iostream> #include <cstring> using namespace std; const int N = 110; int n,T,idx,h[N*N],match[N*N]; int xx[4] = {-1,1,0,0},yy[4] = {0,0,-1,1}; bool vis[N][N],st[N*N]; struct Road{ int to,ne; }road[N*N<<2];//求二分圖匹配一定需要將點劃分為兩邊 void add(int a,int b) { road[idx].to = b,road[idx].ne = h[a],h[a] = idx++; } int find(int u) { for(int i=h[u];~i;i=road[i].ne) { int v = road[i].to; if(st[v]) continue; st[v] = 1; if(!match[v]||find(match[v])) { match[v] = u; return 1; } } return 0; } int main() { // freopen("in.txt","r",stdin); scanf("%d%d",&n,&T); memset(h,-1,sizeof h); while(T--) { int x,y; scanf("%d%d",&x,&y); vis[x][y] = 1; } for(int x=1;x<=n;x++) for(int y=1;y<=n;y++) for(int i=0;i<4;i++) { if(vis[x][y]||((x+y)&1)) break; int dx = x+xx[i],dy = y+yy[i]; if(dx>0&&dx<=n&&dy>0&&dy<=n&&!vis[dx][dy]) { int a = (x-1)*n+y; int b = (dx-1)*n+dy; add(a,b); } } int res = 0; for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) if(!vis[i][j]&&(i+j)%2==0)//存在點遞迴繫結正在綁的 { int s = (i-1)*n+j; memset(st,0,sizeof st); if(match[s]) continue; if(find(s)) res++; } printf("%d\n",res); return 0; }