POJ2226 Muddy Fields【二分图最小点覆盖】
2015-04-02 15:20
225 查看
题目链接:
http://poj.org/problem?id=2226
题目大意:
有一个r行c列的方格组成的田地。里边有若干个方格充满泥水,其余的方格是草。要用宽度为1、长度
不限的长木板把充满泥水的方格覆盖掉,但不能覆盖草地,同时只能按行覆盖或是按列覆盖,不能斜着
覆盖。问:最少要用多少木板。
思路:
这道题感觉很难想。看了看网上的题解,居然很巧妙的构造了二分图来求解,很是精妙。我们把同一行
一段连续的泥水方格作为一个顶点,把这些点作为二分图的一个集合,再把同一列一段连续的泥水方格
作为一个顶点,把这些点作为二分图的另一个集合。如果两个集合的点有相交,就建立一条边。两个集
合相交说明相交的地方为原图上的一个泥水方格,边和泥水方格就变成了一一对应的关系。如果选择了
一个边(木板),则与该边(木板)关联的所有泥方格都会被覆盖掉。那么问题就变成了求解二分图最小点集
覆盖。二分图最小点集覆盖 = 二分图最大匹配,用匈牙利算法来解决。
这道题有一个地方要注意,就是二分图点的个数问题。考虑到原图规模是55*55,而连续的泥水方格当
做一个点,现在为了求出最多有多少个点,假设所有的泥水方格都不连续,即每个泥水方格都是独立的,
周围都是草地。则最多有23*23+22*22 = 1013个点,即为二分图一个集合点的个数。
AC代码:
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
using namespace std;
const int MAXN = 1016;
bool Map[MAXN][MAXN],Mask[MAXN];
int NX,NY;
int cx[MAXN],cy[MAXN];
char G[60][60];
int fa[60][60],fb[60][60];
int FindPath(int u)
{
for(int i = 0; i < NY; ++i)
{
if(Map[u][i] && !Mask[i])
{
Mask[i] = 1;
if(cy[i] == -1 || FindPath(cy[i]))
{
cy[i] = u;
cx[u] = i;
return 1;
}
}
}
return 0;
}
int MaxMatch()
{
for(int i = 0; i < NX; ++i)
cx[i] = -1;
for(int i = 0; i < NY; ++i)
cy[i] = -1;
int res = 0;
for(int i = 0; i < NX; ++i)
{
if(cx[i] == -1)
{
for(int j = 0; j < NY; ++j)
Mask[j] = 0;
res += FindPath(i);
}
}
return res;
}
int main()
{
int N,M;
while(~scanf("%d%d",&N,&M))
{
for(int i = 0; i < N; ++i)
scanf("%s",G[i]);
memset(fa,0,sizeof(fa));
memset(fb,0,sizeof(fb));
memset(Map,0,sizeof(Map));
int n = 0;
for(int i = 0; i < N; ++i)
{
int sum = 0;
for(int j = 0; j < M; ++j)
{
if(G[i][j] == '*')
{
fa[i][j] = n;
if(G[i][j+1]!='*')
n++;
}
}
}
int m = 0;
for(int i = 0; i < M; ++i)
{
for(int j = 0; j < N; ++j)
{
if(G[j][i] == '*')
{
fb[j][i] = m;
if(G[j+1][i]!= '*')
m++;
}
}
}
for(int i = 0; i < N; ++i)
for(int j = 0; j < M; ++j)
if(G[i][j] == '*')
Map[fa[i][j]][fb[i][j]] = 1;
NX = n,NY = m;
printf("%d\n",MaxMatch());
}
return 0;
}
http://poj.org/problem?id=2226
题目大意:
有一个r行c列的方格组成的田地。里边有若干个方格充满泥水,其余的方格是草。要用宽度为1、长度
不限的长木板把充满泥水的方格覆盖掉,但不能覆盖草地,同时只能按行覆盖或是按列覆盖,不能斜着
覆盖。问:最少要用多少木板。
思路:
这道题感觉很难想。看了看网上的题解,居然很巧妙的构造了二分图来求解,很是精妙。我们把同一行
一段连续的泥水方格作为一个顶点,把这些点作为二分图的一个集合,再把同一列一段连续的泥水方格
作为一个顶点,把这些点作为二分图的另一个集合。如果两个集合的点有相交,就建立一条边。两个集
合相交说明相交的地方为原图上的一个泥水方格,边和泥水方格就变成了一一对应的关系。如果选择了
一个边(木板),则与该边(木板)关联的所有泥方格都会被覆盖掉。那么问题就变成了求解二分图最小点集
覆盖。二分图最小点集覆盖 = 二分图最大匹配,用匈牙利算法来解决。
这道题有一个地方要注意,就是二分图点的个数问题。考虑到原图规模是55*55,而连续的泥水方格当
做一个点,现在为了求出最多有多少个点,假设所有的泥水方格都不连续,即每个泥水方格都是独立的,
周围都是草地。则最多有23*23+22*22 = 1013个点,即为二分图一个集合点的个数。
AC代码:
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
using namespace std;
const int MAXN = 1016;
bool Map[MAXN][MAXN],Mask[MAXN];
int NX,NY;
int cx[MAXN],cy[MAXN];
char G[60][60];
int fa[60][60],fb[60][60];
int FindPath(int u)
{
for(int i = 0; i < NY; ++i)
{
if(Map[u][i] && !Mask[i])
{
Mask[i] = 1;
if(cy[i] == -1 || FindPath(cy[i]))
{
cy[i] = u;
cx[u] = i;
return 1;
}
}
}
return 0;
}
int MaxMatch()
{
for(int i = 0; i < NX; ++i)
cx[i] = -1;
for(int i = 0; i < NY; ++i)
cy[i] = -1;
int res = 0;
for(int i = 0; i < NX; ++i)
{
if(cx[i] == -1)
{
for(int j = 0; j < NY; ++j)
Mask[j] = 0;
res += FindPath(i);
}
}
return res;
}
int main()
{
int N,M;
while(~scanf("%d%d",&N,&M))
{
for(int i = 0; i < N; ++i)
scanf("%s",G[i]);
memset(fa,0,sizeof(fa));
memset(fb,0,sizeof(fb));
memset(Map,0,sizeof(Map));
int n = 0;
for(int i = 0; i < N; ++i)
{
int sum = 0;
for(int j = 0; j < M; ++j)
{
if(G[i][j] == '*')
{
fa[i][j] = n;
if(G[i][j+1]!='*')
n++;
}
}
}
int m = 0;
for(int i = 0; i < M; ++i)
{
for(int j = 0; j < N; ++j)
{
if(G[j][i] == '*')
{
fb[j][i] = m;
if(G[j+1][i]!= '*')
m++;
}
}
}
for(int i = 0; i < N; ++i)
for(int j = 0; j < M; ++j)
if(G[i][j] == '*')
Map[fa[i][j]][fb[i][j]] = 1;
NX = n,NY = m;
printf("%d\n",MaxMatch());
}
return 0;
}
相关文章推荐
- [USACO2005][POJ2226]Muddy Fields(二分图最小点覆盖)
- poj 2226 Muddy Fields(二分图——最小点覆盖)
- poj 2226 Muddy Fields (转化成二分图的最小覆盖)
- POJ2226 Muddy Fields——最小点覆盖问题
- poj2226(*行列模型,二分图最小顶点覆盖)
- POJ2226 Muddy Fields——最小点覆盖问题——Pku2226
- POJ2226 Muddy Fields 二分图求最小覆盖点
- poj 2226 Muddy Fields(二分图最小点覆盖)
- POJ 2226-Muddy Fields(二分图_最小点覆盖+神建图orz)
- POJ2226 Muddy Fields 二分匹配 最小顶点覆盖 好题
- POJ 2226 Muddy Fields【二分图最小点覆盖】
- POJ2226 Muddy Fields(二分图最小点覆盖集)
- POJ-2226-Muddy Fields-二分图-最小点覆盖
- [POJ] 2226 Muddy Fields(二分图最小点覆盖)
- POJ - 2226 Muddy Fields 二分图 最小点覆盖
- 最小点覆盖 poj2226 Muddy Fields
- POJ 1325 && ZOJ 1364--Machine Schedule【二分图 && 最小点覆盖数】
- 二分图(最小路径覆盖)
- POJ 2226 二分图 最小点覆盖
- 二分图大讲堂——彻底搞定最大匹配数(最小覆盖数)、最大独立数、最小路径覆盖、带权最优匹配