hdu 1507 Uncle Tom's Inherited Land* 最大匹配

#include <cstdio>
#include <cstring>
#include <cmath>
#include <vector>
#include <algorithm>
#include <iostream>
using namespace std;
const int maxn=10010;
const int maxc=110;
vector<int>e[maxn];
int map[maxc][maxc];
int vis[maxn],pre[maxn];
int dir[4][2]={{-1,0},{1,0},{0,-1},{0,1}};
int find(int u)//判断增广路是否存在,匈牙利算法
{
    int i,j,v;
    for(i=0;i<e[u].size();i++)
    {
        v=e[u][i];
        if(!vis[v])
        {
            vis[v]=1;
            if(pre[v]==-1||find(pre[v]))
            {
                pre[v]=u;
                return 1;
            }
        }
    }
    return 0;
}
int main()
{
    int n,m,num;
    while(scanf("%d%d",&n,&m)!=EOF)
    {
        if(n==0&&m==0)break;
        scanf("%d",&num);
        int i,j,k,a,b,x,y,x1,y1,x2,y2;
        memset(map,0,sizeof(map));
        for(i=0;i<num;i++)
        {
            scanf("%d%d",&a,&b);
            map[a][b]=1;
        }
        for(i=1;i<=n*m;i++)
            e[i].clear();
        for(i=1;i<=n;i++)
        {
            for(j=1;j<=m;j++)
            {
                if(!map[i][j]&&(i+j)%2)
                {
                    for(k=0;k<4;k++)
                    {
                        x=i+dir[k][0];
                        y=j+dir[k][1];
                        if(x<=0||y<=0||x>n||y>m||map[x][y])continue;
                        e[(i-1)*m+j].push_back(((x-1)*m+y));
                    }
                }
            }
        }
        int ans=0;
        memset(pre,-1,sizeof(pre));
        for(i=1;i<=n*m;i++)
        {
            memset(vis,0,sizeof(vis));
            ans+=find(i);
        }
        printf("%d\n",ans);
        for(i=1;i<=n*m;i++)
        {
            if(pre[i]==-1)continue;
            if(pre[i]%m==0){x1=pre[i]/m;y1=m;}
            else{x1=pre[i]/m+1;y1=pre[i]%m;}
            if(i%m==0){x2=i/m;y2=m;}
            else{x2=i/m+1;y2=i%m;}
            printf("(%d,%d)--(%d,%d)\n",x1,y1,x2,y2);
        }
        printf("\n");
    }
    return 0;
}
/*
    n*m的矩阵,标号1~n*m,则以相邻空白格的编号建边,则边表示的就是可选的1*2的格子。
    分二部图:由于横纵坐标相加为奇数的点,跟它相邻的必定是横纵坐标相加为偶数的点,
且所有奇数点加相邻偶数点覆盖所有图上的点。由此我们可以从奇数点到偶数点建二部图。
    最大匹配:二分图G中,找出边数最大的子图M,使得M中各条边均无公共顶点,则M为最大匹配。
    所求答案ans=最大匹配数,因为所求情况必定符合匹配,因为不能有覆盖的格子,因而最大匹配数就是所求最大的1*2格数
    
    最后pre记录的符合最大匹配的点和它的相连点,即所求边
*/

你可能感兴趣的:(最大匹配)