HDU 4185&&POJ 3020 二分图匹配

这两题的建图方式有相似之处,故放在一起整理。

HDU 4185 Oil Skimming

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

Problem Description

Thanks to a certain "green" resources company, there is a new profitable industry of oil skimming. There are large slicks of crude oil floating in the Gulf of Mexico just waiting to be scooped up by enterprising oil barons. One such oil baron has a special plane that can skim the surface of the water collecting oil on the water's surface. However, each scoop covers a 10m by 20m rectangle (going either east/west or north/south). It also requires that the rectangle be completely covered in oil, otherwise the product is contaminated by pure ocean water and thus unprofitable! Given a map of an oil slick, the oil baron would like you to compute the maximum number of scoops that may be extracted. The map is an NxN grid where each cell represents a 10m square of water, and each cell is marked as either being covered in oil or pure water.

Input

The input starts with an integer K (1 <= K <= 100) indicating the number of cases. Each case starts with an integer N (1 <= N <= 600) indicating the size of the square grid. Each of the following N lines contains N characters that represent the cells of a row in the grid. A character of '#' represents an oily cell, and a character of '.' represents a pure water cell.

Output

For each case, one line should be produced, formatted exactly as follows: "Case X: M" where X is the case number (starting from 1) and M is the maximum number of scoops of oil that may be extracted.

Sample Input

 

1 6

......

.##...

.##...

....#.

....##

......

Sample Output

 

Case 1: 3

题意:

给你一个nxn的网格,#代表油,.代表水,用1x2的铲子去铲,最多能铲到多少纯油。

分析:

思路很容易想到,把每一个#看作一个顶点,如果它的上下左右有#,就在这两个顶点之间连一条边。但是,这样建图之后会发现相邻两点之间的边都添加了两次。 所以,要在求出来的匹配数上除以2. 

上代码:

 

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
const int maxn=605;
char pic[maxn][maxn];
int g[maxn][maxn],num[maxn][maxn];
int linker[maxn];
bool used[maxn];
int uN,vN;
bool dfs(int u)
{
	int v;
	for(v=1;v<vN;v++)
	{
		if(g[u][v]&&!used[v])
		{
			used[v]=true;
			if(linker[v]==-1||dfs(linker[v]))
			{
				linker[v]=u;
				return true;
			}
		}
	}
	return false;
}
int hungary()
{
	int res=0;
	int u;
	memset(linker,-1,sizeof(linker));
	for(u=1;u<uN;u++)
	{
		memset(used,0,sizeof(used));
		if(dfs(u)) res++;
	}
	return res;
}
int main()
{
	//freopen("in.txt","r",stdin);
	//freopen("out.txt","w",stdout);
	int t,n;
	scanf("%d",&t);
	for(int a=1;a<=t;a++)
	{
		memset(pic,0,sizeof(pic));
		memset(num,0,sizeof(num));
		memset(g,0,sizeof(g));
		scanf("%d",&n);uN=1;
		for(int i=0;i<n;i++)//建图
		{
			scanf("%s",pic[i]);
			for(int j=0;j<n;j++)
			{
				if(pic[i][j]=='#')//重新编号
				num[i][j]=uN++;//从1开始
			}
		}
		for(int i=0;i<n;i++)
		{
			for(int j=0;j<n;j++)
			{
				int now=num[i][j],b=num[i-1][j],c=num[i+1][j];
				int d=num[i][j-1],e=num[i][j+1];
				if(now)
				{
					if(b&&i-1>=0) g[now][b]=1;//注意下标,之前没注意wa了一发 
					if(c) g[now][c]=1;
					if(d&&j-1>=0) g[now][d]=1;//注意下标 
					if(e) g[now][e]=1;
				}
			}
		}
		vN=uN;
		int ans=hungary()/2;
		printf("Case %d: %d\n",a,ans);
	}
	return 0;
}

 

POJ 3020 Antenna Placement

题目链接:http://poj.org/problem?id=3020

Description

The Global Aerial Research Centre has been allotted the task of building the fifth generation of mobile phone nets in Sweden. The most striking reason why they got the job, is their discovery of a new, highly noise resistant, antenna. It is called 4DAir, and comes in four types. Each type can only transmit and receive signals in a direction aligned with a (slightly skewed) latitudinal and longitudinal grid, because of the interacting electromagnetic field of the earth. The four types correspond to antennas operating in the directions north, west, south, and east, respectively. Below is an example picture of places of interest, depicted by twelve small rings, and nine 4DAir antennas depicted by ellipses covering them. 
 
Obviously, it is desirable to use as few antennas as possible, but still provide coverage for each place of interest. We model the problem as follows: Let A be a rectangular matrix describing the surface of Sweden, where an entry of A either is a point of interest, which must be covered by at least one antenna, or empty space. Antennas can only be positioned at an entry in A. When an antenna is placed at row r and column c, this entry is considered covered, but also one of the neighbouring entries (c+1,r),(c,r+1),(c-1,r), or (c,r-1), is covered depending on the type chosen for this particular antenna. What is the least number of antennas for which there exists a placement in A such that all points of interest are covered? 
 

Input

On the first row of input is a single positive integer n, specifying the number of scenarios that follow. Each scenario begins with a row containing two positive integers h and w, with 1 <= h <= 40 and 0 < w <= 10. Thereafter is a matrix presented, describing the points of interest in Sweden in the form of h lines, each containing w characters from the set ['*','o']. A '*'-character symbolises a point of interest, whereas a 'o'-character represents open space. 
 

Output

For each scenario, output the minimum number of antennas necessary to cover all '*'-entries in the scenario's matrix, on a row of its own.

Sample Input

2
7 9
ooo**oooo
**oo*ooo*
o*oo**o**
ooooooooo
*******oo
o*o*oo*oo
*******oo
10 1
*
*
*
o
*
*
*
*
*
*

Sample Output

17
5

题意:

       全球航空研究中心已经分配了在瑞典建造第五代移动电话网的任务。他们找到这份工作的最明显原因是他们发现了一种新的高抗噪天线。它被称为4DAIR,它有四种类型。由于地球的相互作用的电磁场,每种类型只能在具有(略微倾斜的)纬度和纵向网格的方向上发送和接收信号。这四种类型分别对应于在北,西,南和东方向上运行的天线。下面是十二个小环描绘的感兴趣的地方的例子,以及覆盖它们的椭圆描绘的九个4DAir天线。显然,希望使用尽可能少的天线,但仍然为每个感兴趣的地方提供覆盖。我们将问题建模如下:设a为描述瑞典表面的矩形矩阵,其中一个入口是一个感兴趣的点,必须由至少一个天线或空的空间覆盖。 (C + 1,r),(c,r + 1)和(c + 1)根据为该特定天线选择的类型,覆盖(c-1,r)或(c,r-1)。在A中放置的最小天线数是多少,以便覆盖所有兴趣点

分析:

       不要被描述图里的圈圈误导了,其实这题的描述和上题大致差不多,但是这是一道最小路径覆盖的题。最小路径覆盖是指用尽量少的不相交简单路径覆盖二分图中的所有顶点。题中要求我们覆盖所有兴趣点,其实也就是覆盖图中所有的顶点。建图的方式和上题一样(因为题中的天线是可以往四个方向延伸的,如果建有向图,天线会存在某些方向无法延伸,与题意相违背。)

代码:

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
const int maxn=1005;
char pic[45][15];
int num[45][15];
int g[maxn][maxn],linker[maxn];
bool used[maxn];
int uN,vN;
bool dfs(int u)
{
	for(int v=1;v<vN;v++)
	{
		if(g[u][v]&&!used[v])
		{
			used[v]=true;
			if(linker[v]==-1||dfs(linker[v]))
			{
				linker[v]=u;
				return true;
			}
		}
	}
	return false;
}
int hungary()
{
	int res=0;
	memset(linker,-1,sizeof(linker));
	for(int u=1;u<uN;u++)
	{
		memset(used,0,sizeof(used));
		if(dfs(u)) res++;
	}
	return res;
}
int main()
{
	//freopen("in.txt","r",stdin);
	//freopen("out.txt","w",stdout);
	int t;
	int n,m;
	scanf("%d",&t);
	while(t--)
	{
		scanf("%d%d",&n,&m);
		int tmp=1;
		memset(g,0,sizeof(g));
		memset(num,0,sizeof(num));
		for(int i=0;i<n;i++)
		{
			scanf("%s",pic[i]);
			for(int j=0;j<m;j++)
			{
				if(pic[i][j]=='*')
				num[i][j]=tmp++;
			}
		}
		for(int i=0;i<n;i++)
		{
			for(int j=0;j<m;j++)
			{
				int a=num[i][j],b=num[i-1][j],c=num[i+1][j];
				int d=num[i][j-1],e=num[i][j+1];
				if(a)
				{
					if(i-1>=0&&b)
						g[a][b]=1;
					if(i+1<n&&c)
						g[a][c]=1;
					if(j-1>=0&&d)
						g[a][d]=1;
					if(j+1<m&&e)
						g[a][e]=1;
				}
			}
		}
		uN=vN=tmp;
		int mid=hungary();
		printf("%d\n",tmp-1-mid/2);
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_41279172/article/details/81660580