Problem Description
There is a piece of grids land of size n×m. Chandler and his team take responsibility to guard it. There are some searchlights on some pieces and each of them has a capability to lighten a distance towards four directions: north, south, east and west. Different searchlight has different lightening capability shown in levels. Searchlight with level k means that it can lighten k grids (including the gird that the searchlight stands in) along any of the four directions. Shown in following figure, there is a searchlight of level 3 and the shadow grids are ones that can be lightened by it. Particularly, searchlight of level 1 means that it can only lighten the grid in which the searchlight stands.

Each searchlight has a maximum level. You can decrease a searchlight’s level to save the energy. A searchlight whose maximum level is k can be turned to level k, k-1, k-2, …, 1 and 0. Level 0 means turning off the searchlight.

A grid is well-guarded if and only if at least one of the following two conditions is satisfied:
1.There is a searchlight in this grid, and it is not switched to level 0 (the light is on).
2.The grid is lightened by at least two searchlights. One lightens it in horizontal direction (east or west), and another lightens it in vertical direction (north or south).

Chandler asks you to help finding a solution that he can turn on some of the searchlights so that:
1.All the grids are well-guarded.
2.All the searchlights turned on are in a same level.
3.That same level mentioned above is as small as possible.
More specifically, if you choose a same level Q, then all the searchlights whose maximum level are less than Q have to be turned off. Please help him to find a solution with the minimum same level.

 
Input
The input file contains several test cases.

For each test case, the first line is two integers n and m, representing a grids land of size n×m. (0<n<=100, 0<m<=10000). Following n lines describe an n×m matrix in which ai,j means the maximum level of the searchlight in grid (i, j). ai,j can be zero, which means there is no searchlight on that grid. For all the cases, ai, j<=10000.

The input file ends with a line containing two zeros.

 
Output
For each test case, output a single line with an integer, representing the minimum level you have found. If there is no such a solution, output “NO ANSWER!”
 
题目大意:在一个n*m的矩阵里,每个格子都有一个灯,每个灯可以调节灯光大小(不超过上限)。给出每个灯的灯光大小,现要求把所有灯光调到同一个大小(小于这个大小的灯就不打开)。要求每一个格子必须开着灯或者必须被东西方向和南北方向的灯同时照到。问这个大小最小是多少。
思路:从小到大枚举灯光大小K,把所有小于K的灯依次灭了。用并查集维护所有没有开灯的地方,有多少个格子(每次灭掉一个灯,就把这个灯的左右的没有开灯的格子和自己的格子合并,上下同理),每一行每一列互不影响,各自维护即可。对于每一堆没有开灯的格子,设格子数为size,若他们挨着边界,那么灯光大小至少为size + 1(只有一边有灯照着);若没挨着边界,那么灯光大小至少为(size + 1) / 2(两边都有灯照着,一个要照一半的大小。若把所有灯都灭了都不行,输出NO ANSWER!。
 
代码(625MS):
 #include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <queue>
using namespace std;
typedef long long LL; const int MAXN = ;
const int MAXM = ; struct Node {
int a, x, y;
bool operator < (const Node &rhs) const {
if(a != rhs.a) return a < rhs.a;
if(x != rhs.x) return x < rhs.x;
return y < rhs.y;
}
} p[MAXN * MAXM]; int mat[MAXN][MAXM];
int xfa[MAXM][MAXN], yfa[MAXN][MAXM];
int xsize[MAXM][MAXN], ysize[MAXN][MAXM];
int n, m, s; void init() {
for(int j = ; j <= m; ++j)
for(int i = ; i <= n; ++i) xfa[j][i] = i, xsize[j][i] = ;
for(int i = ; i <= n; ++i)
for(int j = ; j <= m; ++j) yfa[i][j] = j, ysize[i][j] = ;
} int find_set(int *fa, int x) {
return fa[x] == x ? x : fa[x] = find_set(fa, fa[x]);
} void merge(int *fa, int *size, int x, int y) {
int fx = find_set(fa, x), fy = find_set(fa, y);
if(size[fx] < size[fy]) swap(fx, fy);
size[fx] += size[fy];
fa[fy] = fx;
} int solve() {
int largest = ;
for(int k = , i = ; i < s; ++k) {
if(k - >= largest) return k;
while(i < s && p[i].a == k) {
int x = p[i].x, y = p[i].y;
if(x - >= && mat[x - ][y] <= k) merge(xfa[y], xsize[y], x - , x);
if(x + <= n && mat[x + ][y] < k) merge(xfa[y], xsize[y], x, x + );
if(y - >= && mat[x][y - ] <= k) merge(yfa[x], ysize[x], y - , y);
if(y + <= m && mat[x][y + ] < k) merge(yfa[x], ysize[x], y, y + ); int fx = find_set(xfa[y], x), fy = find_set(yfa[x], y);
if(xsize[y][fx] == n || ysize[x][fy] == m) return -; if(find_set(xfa[y], ) == fx || find_set(xfa[y], n) == fx)
largest = max(largest, xsize[y][fx]);
else largest = max(largest, (xsize[y][fx] + ) / );
if(find_set(yfa[x], ) == fy || find_set(yfa[x], m) == fy)
largest = max(largest, ysize[x][fy]);
else largest = max(largest, (ysize[x][fy] + ) / ); ++i;
}
}
return -;
} int main() {
while(scanf("%d%d", &n, &m) != EOF) {
if(n == && m == ) break;
s = ;
for(int i = ; i <= n; ++i) {
for(int j = ; j <= m; ++j) {
scanf("%d", &mat[i][j]);
p[s].x = i;
p[s].y = j;
p[s++].a = mat[i][j];
}
}
sort(p, p + s);
init();
int ans = solve();
if(ans == -) puts("NO ANSWER!");
else printf("%d\n", ans);
}
}

HDU 3688 Searchlights(并查集)的更多相关文章

  1. HDU 2818 (矢量并查集)

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=2818 题目大意:每次指定一块砖头,移动砖头所在堆到另一堆.查询指定砖头下面有几块砖头. 解题思路: ...

  2. hdu 1116 欧拉回路+并查集

    http://acm.hdu.edu.cn/showproblem.php?pid=1116 给你一些英文单词,判断所有单词能不能连成一串,类似成语接龙的意思.但是如果有多个重复的单词时,也必须满足这 ...

  3. Bipartite Graph hdu 5313 bitset 并查集 二分图

    题目:http://acm.hdu.edu.cn/showproblem.php?pid=5313 题意: 给出n个顶点,m条边,问最多添加多少条边使之构成一个完全二分图 存储结构: bitset   ...

  4. hdu 3081(二分+并查集+最大流||二分图匹配)

    Marriage Match II Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others ...

  5. 2015 ACM/ICPC Asia Regional Changchun Online HDU - 5441 (离线+并查集)

    题目:http://acm.hdu.edu.cn/showproblem.php?pid=5441 题意:给你n,m,k,代表n个城市,m条边,k次查询,每次查询输入一个x,然后让你一个城市对(u,v ...

  6. hdu 3536【并查集】

    hdu 3536 题意: 有N个珠子,第i个珠子初始放在第i个城市.有两种操作: T A B:把A珠子所在城市的所有珠子放到B城市.  Q A:输出A珠子所在城市编号,该城市有多少个珠子,该珠子转移了 ...

  7. HDU 1829 分组并查集

    题意:有两种性别,每组数据表示是男女朋友,判断输入的几组数据是否有同性恋 思路:http://blog.csdn.net/iaccepted/article/details/24304087 分组并查 ...

  8. HDU 1198(并查集)

    题意:给你11个图,每一个都有管道,然后给一张由这11个正方形中的n个组成的图,判断有几条连通的管道: 思路:在大一暑假的时候做过这道题,当时是当暴力来做的,正解是并查集,需要进行一下转换: 转换1: ...

  9. HDU 4496 D-City(并查集,逆思维)

    题目 熟能生巧...常做这类题,就不会忘记他的思路了... //可以反过来用并查集,还是逐个加边,但是反过来输出...我是白痴.....又没想到 //G++能过,C++却wa,这个也好奇怪呀... # ...

随机推荐

  1. RequestContextListener有什么用

    问题: java.lang.IllegalStateException: No thread-bound request found: Are you referring to request att ...

  2. Qt工具知多少(一目了然)

    一级题目: Qt Designer — 所见即所得的界面设计工具, 可以用拖拽的方式将控件排布在界面上,支持layout, 支持signal/slot编辑. 生成的文件保存为ui格式, ui是xml格 ...

  3. CentOS联网

    虚拟机那里选择NAT模式 用vi /etc/sysconfig/network-scripts/ifcfg-eth0进到网卡文件修改ONBOOT=yes.意思是启动网卡 (注意在vi里,需要编辑时要按 ...

  4. python join split

    本文记录python,join和split函数的用法. 参考 http://blog.csdn.net/doiido/article/details/43538833 http://blog.csdn ...

  5. 2.准备Python编译环境

    2.准备Python编译环境 2.1下载Python2.7.6.tgz.ipython1.2.1.tgz.sqlite-autoconf-3071401.tar.gz 2.2安装Python2.7.6 ...

  6. MySQL · 性能优化 · 条件下推到物化表

    MySQL · 性能优化 · 条件下推到物化表 http://mysql.taobao.org/monthly/2016/07/08/ 背景 MySQL引入了Materialization(物化)这一 ...

  7. 解决 SVN cleanup 任务中断导致无法 update

    解决 SVN cleanup 任务中断导致无法 update 今天在更新 svn 时, TortoiseSVN 一直在提示要进行 cleanup ,而执行 cleanup 时又提示: Cleanup ...

  8. 使用Storm实现实时大数据分析

    摘要:随着数据体积的越来越大,实时处理成为了许多机构需要面对的首要挑战.Shruthi Kumar和Siddharth Patankar在Dr.Dobb’s上结合了汽车超速监视,为我们演示了使用Sto ...

  9. LIB和DLL的区别与使用

    转这篇文章是因为以前有个误区,以为lib为静态库,dll为动态库,这理解并不错,但不全面.lib分两种的:(1) lib包含所有内容的静态库,应用程序用它即可,这是我理解的一种(2) lib只包含头部 ...

  10. CTE计算层级关系

    推广渠道表有ParentID字段,代表上下层级关系.现要统计每个推广员,推广了多少人? --创建表结构,插入测试数据 USE DBA_Monitor GO CREATE TABLE [dbo].[TG ...