P10945 Place the Robots
对于本题,我们都可以想到车的放置(即是放置车使得每个车两两不攻击),此题我们的做法是二分图匹配.
因此本题我们自然而然地就有往这个方面想的思路,但是我们必须要处理墙的这个问题,即使一些机器人同时在一列,但是他们中间却有一堵墙,也不会互相伤害.
所以我们可以将有墙分隔的行或列看成两个独立的个体,我们可以先预处理列,将每列先分块,分别给予每个点(非墙)编号,接着把行分好的块也提供编号与当前点预处理好的列的编号连边即可.
#include<bits/stdc++.h>
using namespace std;
const int N=10010;
int T,m,n,tot1,tot2;
int a[N][N],g[N][N],vis[N],ma[N];
char c[N][N];
bool dfs(int u){for(int i=1;i<=tot1;i++){if(!a[u][i]||vis[i]) continue;vis[i]=1;if(!ma[i]||dfs(ma[i])){ma[i]=u;return 1;}}return 0;
}
int main(){cin>>T;for(int k=1;k<=T;k++){cin>>m>>n;memset(ma,0,sizeof(ma));memset(a,0,sizeof(a));tot1=tot2=0;//多测需要清空数据for(int i=1;i<=m;i++){for(int j=1;j<=n;j++) cin>>c[i][j];}for(int j=1;j<=n;j++){//先将列预处理tot1++;for(int i=1;i<=m;i++){if(c[i][j]!='#'){g[i][j]=tot1;}else tot1++;//如果是墙就把块数增加}}for(int i=1;i<=m;i++){tot2++;for(int j=1;j<=n;j++){if(c[i][j]=='o'){a[tot2][g[i][j]]=1;//读取预处理的列的块数与他连边}else if(c[i][j]=='#') tot2++;}}int ans=0;for(int i=1;i<=tot2;i++){memset(vis,0,sizeof(vis));ans+=dfs(i);}cout<<"Case :"<<k<<"\n"<<ans<<"\n";}return 0;
}```[P10945 Place the Robots](https://www.luogu.com.cn/problem/P10945 "P10945 Place the Robots")