POJ 3020 Antenna Placement 【最大独立集】

Antenna Placement
Time Limit: 1000MSMemory Limit: 65536K
Total Submissions: 3760Accepted: 1831

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

Source

Svenskt Mästerskap i Programmering/Norgesmesterskapet 2001

随便写了个二分图匹配最后竟然凑过去了。。
怎么说呢,二分图的这些性质,或者说图的这些性质在二分图上的体现和统计都好神奇啊。
有向无环图的最小路径覆盖(数)=二分图的最小边覆盖集(数)=二分图的最大独立集(数)=全集-二分图的最小点覆盖集(数)=全集-二分图的最大匹配数
粗略的说明,最大独立集和最大匹配的关系。
假设一开始图中无边,最大独立集=总点数;当每增加一个匹配,图中就少了一个独立集。当达到最大匹配,不能再增,那么当前独立集数目已达到最大,即为最大独立集。反过来说,由最大独立集构建二分图,对应的匹配图就是最大匹配图;反证之,如果匹配可以增加,那么独立集数必将减小,得证。
好难啊二分图。
图中任意相邻的两个点之间可以连边,也即可以构成匹配。求出最大匹配之后,其实就相当于在图中去掉了多少个点,然后用原点数减去最大匹配数就是剩下的点数,也就是需要覆盖的数目,即答案。

总觉得这玩意儿说不清- -二分图、行列二分图(网格图)总有一些很奇妙的性质,尤其是当出现矛盾连边和覆盖问题的时候。用二分图匹配什么的凑凑就能过了。


这题里面相邻的两点连边,题目就抽象为最小边覆盖集问题,用最少边覆盖最多(所有)点的问题。

现在工夫不够深啊,希望等哪天重新回头看,能有一些不一样的想法。

给一个参考链接吧,虽然觉得里面有些东西说得很奇怪:

代码:(求了无向匹配,于是除2)
#include <iostream>
#include 
<cstdio>
#include 
<cmath>
#include 
<cstring>
using namespace std;
#define maxn 405
#define maxh 42
#define maxw 12
bool in[maxh][maxw];
bool map[maxn][maxn];
bool vis[maxn];
int mac[maxn];
int num[maxh][maxw];
int h,w,n;
bool find(int x)
{
    
for(int i = 1;i <= n;i++)
    {
        
if(map[x][i] && !vis[i])
        {
            vis[i] 
= true;
            
if(!mac[i] || find(mac[i]))
            {
                mac[i] 
= x;
                
return true;
            }
        }
    }
    
return false;
}
void gao()
{
    scanf(
"%d %d",&h,&w);
    n 
= h * w;
    
int tot = 0;
    
for(int i = 1;i <= h;i++)
        
for(int j = 1;j <= w;j++)
        {
            
char opt;
            scanf(
" %c",&opt);
            
in[i][j] = (opt == '*')?1:0;
            
if(opt == '*')tot++;
            num[i][j] 
= (i - 1* w + j;
        }
    memset(map,
0,sizeof(map));
    memset(mac,
0,sizeof(mac));
    
for(int i = 1;i <= h;i++)
        
for(int j = 1;j <= w - 1;j++)
            
if(in[i][j] && in[i][j + 1])
                map[num[i][j]][num[i][j
+1]]=map[num[i][j+1]][num[i][j]]=1;
    
for(int j = 1;j <= w;j++)
        
for(int i = 1;i <= h - 1;i++)
            
if(in[i][j] && in[i + 1][j])
                map[num[i][j]][num[i
+1][j]]=map[num[i+1][j]][num[i][j]]=1;
    
for(int i = 1;i <= n;i++)
    {
        memset(vis,
0,sizeof(vis));
        
if(find(i))
            ans
++;
    }
    printf(
"%d\n",tot - ans/2);
}
int main()
{
    
int t;
    scanf(
"%d",&t);
    
for(int i = 0;i < t;i++)gao();
}

posted on 2011-08-05 13:46 BUPT-[aswmtjdsj] @ Penalty 阅读(517) 评论(0)  编辑 收藏 引用 所属分类: 网络流POJ Solution Report


只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理


<2011年10月>
2526272829301
2345678
9101112131415
16171819202122
23242526272829
303112345

导航

统计

常用链接

留言簿(1)

随笔分类(150)

随笔档案(71)

搜索

积分与排名

最新评论

阅读排行榜

评论排行榜