Hdu 1507 Uncle Tom's Inherited Land*

来源:互联网 发布:销售数据分析图表 编辑:程序博客网 时间:2024/06/10 07:20

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1507

题意:给一个N*M的矩阵,一个格子表示一块土地,有些土地被改造成了池塘,问现在如果要按1X2的矩形卖掉土地,最多能卖多少块,并输出方案(任一)。

解法:因为是1X2 的矩阵,所以可以用二分图做最大匹配来做,构图时可以将矩阵按行列和的奇偶进行染色,要保证二部图的建立。

代码:

//Hdu 1507 二分图模板。#include<cstdio>#include<cstring>#include<algorithm>#include<iostream>using namespace std;#define maxn 10010int V;int G[maxn][5]; bool map[101][101]; class Hungary //模板{private:int cnt;     bool vis[maxn]; public:    int match[maxn];     bool DFS(int u) //搜索增广路    {         for(int v,i = 1; i <= G[u][0]; i++){             v = G[u][i];              if(!vis[v]){                 vis[v] = true;                  if(match[v] == 0 || DFS(match[v]) ) //如果找到未匹配的结点,则找到了增广路                 {                           match[v] = u;                           return true;                 }             }         }          return false;    }     int Hungary_match()    {         cnt = 0;         memset(match,0,sizeof(match));          for(int u=1; u<=V; u++)         {                  memset(vis,0,sizeof(vis));                   if(DFS(u)) cnt++;         }          return cnt;    }}H; int n,m,k; void makeBG()    //奇偶二分建图{V = n*m;     for(int i=1; i<=V; i++)G[i][0] = 0;     int u;     for(int i=1; i<=n; i++)    for(int j=1; j<=m; j++)    if(map[i][j] && (i+j)%2 == 1)  //奇数    {u = (i-1)*m+j;if(map[i][j+1])G[u][ ++G[u][0] ] = u+1;if(map[i][j-1])G[u][ ++G[u][0] ] = u-1;if(map[i+1][j])G[u][ ++G[u][0] ] = u+m;if(map[i-1][j])G[u][ ++G[u][0] ] = u-m;    }}void init(){memset(map,1,sizeof(map)); for (int i = 0; i <= n+1; i++)map[i][0] = map[i][m+1] = 0;for (int i = 0; i <= m+1; i++)map[0][i] = map[n+1][i] = 0;}int main(){while(~scanf("%d%d",&n,&m),n+m)    {init();scanf("%d",&k);         int u,v;        while(k--)        {scanf("%d%d",&u,&v);             map[u][v] = 0;        }         makeBG();         printf("%d\n",H.Hungary_match());                int link[maxn];        memset(link,0,sizeof(link));         for(int i=1; i<=V; i++)                 link[ H.match[i] ] = i;         for(int u=1; u<=V; u++)        if(link[u])        {                 v = link[u];  //找u,v对应的行和列。                 printf("(%d,%d)",(u-1)/m+1,(u-1)%m+1); printf("--"); printf("(%d,%d)",(v-1)/m+1,(v-1)%m+1); printf("\n");        }        printf("\n");    }    return 0;}


0 0
原创粉丝点击