analysis:
The key point of this problem is to build a map
At the beginning, I YY had at least three modeling methods
(for example, two points in a grid are packaged into a node of a bipartite graph, directly h*w nodes, and each row and column is a node.)
In fact, we need to change our way of thinking
Set the number of "*" in the grid to tt
We already know the worst: tt
If we set up a device in a grid, it is possible to save one device (the device can cover up to two points)
We can turn the problem into: the biggest savings
Construction drawing:
h*w points in each part
If the position is "*", then we will connect the four directions from x to ta respectively (the connected position must also be "*")
It means that if we place the device at this point, we can choose to save a device near ta
In this way, the biggest matching ans with Hungary is the biggest saving
But because every device is recalculated
So the final answer is: TT ans / 2
tip
Thinking is very important in doing this kind of questions
Principle: if it is difficult, it will be reversed. If it is small, it will become large
Don't forget to initialize
#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
char s[50][12];
int n,h,z;
struct node{
int y,nxt;
};
node way[200000];
int cx[500],cy[500],st[500],tot=0;
bool vis[500];
void add(int u,int w)
{
tot++;
way[tot].y=w;way[tot].nxt=st[u];st[u]=tot;
}
int get(int x,int y)
{
return (x-1)*z+y;
}
int match(int x)
{
for (int i=st[x];i;i=way[i].nxt)
{
int y=way[i].y;
if (!vis[y])
{
vis[y]=1;
if (!cy[y]||match(cy[y]))
{
cx[x]=y; cy[y]=x;
return 1;
}
}
}
return 0;
}
int XYL()
{
memset(cx,0,sizeof(cx));
memset(cy,0,sizeof(cy));
int ans=0;
for (int i=1;i<=n;i++)
if (!cx[i]){
memset(vis,0,sizeof(vis));
ans+=match(i);
}
return ans;
}
int main()
{
int T;
scanf("%d",&T);
while (T--)
{
memset(st,0,sizeof(st)); tot=0;
scanf("%d%d",&h,&z);
n=h*z;
int tt=0;
for (int i=1;i<=h;i++)
scanf("%s",s[i]+1);
for (int i=1;i<=h;i++)
{
for (int j=1;j<=z;j++)
if (s[i][j]=='*')
{
tt++;
int x=get(i,j);
if (i>1&&s[i-1][j]=='*') add(x,get(i-1,j));
if (i<h&&s[i+1][j]=='*') add(x,get(i+1,j));
if (j>1&&s[i][j-1]=='*') add(x,get(i,j-1));
if (j<z&&s[i][j+1]=='*') add(x,get(i,j+1));
}
}
printf("%d\n",tt-XYL()/2);
}
return 0;
}