poj3020 Antenna Placement (Hungary)

Posted by chet23 on Fri, 01 May 2020 05:18:32 +0200

Title Link

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