POJ 3020 Antenna Placement 解题报告

    题意就不说了,求二部图最大匹配。

    问题是怎么建图……

    给定的条件中,h<40,w<10,所以笔者直接默认所有情况的地图都是40*10,当然,超出范围的便是空城o。

    然后给城市编号。一个城市只能和上下左右4个城市公用天线。换个换说就像国际象棋的棋盘一样,黑色格子与白色格子自然分成了二部图。黑色只能和白色匹配。

    编号也很简单了。从第一行开始,第一格是黑色城市1,然后白色城市1,然后黑色城市2,白色城市2……因为所有的图都默认一样大小,所以编号可以重用。

    为了方便知道(i,j)到底是黑色还是白色,我们可以用正数编号表示黑色,负数编号表示白色。

    然后求最大匹配,直接匈牙利过去就好了。

    贴代码,0MS

#include <cstdio>

#include <cstring>



const int maxn=201;

bool mp[maxn][maxn];

bool vis[maxn];

int link[maxn];

int No[41][10];

int n;



bool DFS(int x)

{

    for(int y=1;y<=n;y++)

    {

        if(mp[x][y] && !vis[y])

        {

            vis[y]=true;

            if(link[y]==0 || DFS(link[y]))

            {

                link[y]=x;

                return true;

            }

        }

    }

    return false;

}



int maxMartch()

{

    int count=0;

    for(int x=1;x<=n;x++)

    {

        memset(vis,0,sizeof(vis));

        if(DFS(x))

            count++;

    }

    return count;

}



int main()

{

    int T;

    scanf("%d",&T);



    int index=2;

    for(int i=0;i<40;i++)

        for(int j=0;j<10;j++,index++)

            No[i][j]=(index/2)*((index+i)%2?-1:1);

    n=200;



    while(T--)

    {

        int num=0;

        int w,h;

        scanf("%d%d",&h,&w);

        if(w%2)

            w++;



        char str[2][20];

        memset(mp,0,sizeof(mp));

        memset(link,0,sizeof(link));

        memset(str,0,sizeof(str));

        for(int i=0;i<h;i++)

        {

            scanf("%s",str[i&1]);

            if(str[i&1][0]=='*')

            {

                num++;

                if(str[1-i&1][0]=='*')

                {

                    if(No[i][0]>0)

                        mp[No[i][0]][-No[i-1][0]]=true;

                    else

                        mp[No[i-1][0]][-No[i][0]]=true;

                }

            }

            for(int j=1; j<w; j++)

            {

                if(str[i&1][j]=='*')

                {

                    num++;

                    if(str[i&1][j-1]=='*')

                    {

                        if(No[i][j]>0)

                            mp[No[i][j]][-No[i][j-1]]=true;

                        else

                            mp[No[i][j-1]][-No[i][j]]=true;

                    }



                    if(str[1-i&1][j]=='*')

                    {

                        if(No[i][j]>0)

                            mp[No[i][j]][-No[i-1][j]]=true;

                        else

                            mp[No[i-1][j]][-No[i][j]]=true;

                    }

                }

            }

        }

        printf("%d\n",num-maxMartch());

    }

}

    整个建图是自己想的,好像略似繁琐……不过还好,比赛的时候估计也能这么想到吧。

你可能感兴趣的:(ant)