D180 二分图最大独立集 匈牙利算法 P10939 骑士放置
D180 二分图最大独立集 匈牙利算法 P10939 骑士放置_哔哩哔哩_bilibili
P3355 骑士共存问题 - 洛谷 P10939 骑士放置 - 洛谷
有一个 𝑛×𝑛
的国际象棋棋盘,其中一些位置不能放棋子,问最多可以放多少个马使得这些马不会互相攻击。

思路
日字对角的坐标之和的奇偶性不同,按照格点的奇偶性染色,满足二分图的性质
奇格点的马只能攻击周围 8 个方向日字对角的偶格点的马,偶格点的马同理
把奇格点作为左部点,偶格点作为右部点,建立二分图,能攻击到就连边

目标是找出最多的点互相攻击不到,即找出最多的点,使点之间没有边,即最大独立集。图中最大独立集为 5 个
答案 $=\;n*n\;-$ 禁止放置格数 $-$ 最大匹配数
奇格点数为 $O(N^2)$,连边总数为 $O(N^2)$,时间复杂度为 $O(N^4)$,匈牙利算法依赖数据和搜索次序
参考:D179 二分图最大独立集 匈牙利算法 CF1404E Bricks - 董晓 - 博客园
// 二分图 匈牙利算法 O(V*E) #include<bits/stdc++.h> using namespace std; const int N=210,M=20010; int n,m,cnt,c1,c2,f[N][N],g[N][N]; int px[M],py[M],match[M]; bitset<M> vis; const int dx[8]={1,1,-1,-1,2,2,-2,-2}; const int dy[8]={-2,2,-2,2,-1,1,-1,1}; // const int dx[8]={-2,-1,1,2,2,1,-1,-2}; // const int dy[8]={1,2,2,1,-1,-2,-2,-1}; //TLE 1个点 bool dfs(int u){ for(int i=0; i<8; i++){ //8向搜索 int a=px[u]+dx[i], b=py[u]+dy[i]; if(a<1||b<1||a>n||b>n) continue; //越界 int v=g[a][b]; //女生v if(vis[v] || f[a][b]) continue; //已参与或障碍 vis[v]=1; if(!match[v]||dfs(match[v])){ //v没配对或其男友可退让 match[v]=u; return 1; //配对成功 } } return 0; //配对失败 } int main(){ ios::sync_with_stdio(0);cin.tie(0);cout.tie(0); cin>>n>>m; for(int i=0,x,y; i<m; i++)cin>>x>>y,f[x][y]=1; //障碍格点 for(int i=1; i<=n; i++)for(int j=1; j<=n; j++)if(!f[i][j]){ if((i+j)&1){ g[i][j]=++c1; //奇格点编号 px[c1]=i; py[c1]=j; //编号的坐标 } else g[i][j]=++c2; //偶格点编号 } for(int i=1; i<=c1; i++){ //枚举奇格点编号 vis=0; cnt+=dfs(i); } cout<<n*n-m-cnt; }
浙公网安备 33010602011771号