问题描述

秋之国首都下了一场暴雨,由于秋之国地势高低起伏,不少地方出现了积水。

秋之国的首都可以看成一个 n 行 m 列的矩阵,第 i 行第 j 列的位置高度为 ai,j,首都以外的地方的高度可以都看成 0。我们假设下的雨无限多,暴雨时,水位线超过了所有位置的高度。暴雨结束后,如果有雨水的高度超过的四相邻(上下左右)的位置的高度,水就会流过去,如果流到了首都外,水会消失。你需要求出最后每个位置的积水高度。

输入格式

第一行两个非负整数 n,m。

接下来 n 行,每行 m 个整数,表示 ai,j。

输出格式

输出 n 行,每行 m 个整数,表示每个位置的积水高度。

样例输入

3 3

4 4 0

2 1 3

3 3 -1

样例输出

0 0 0

0 1 0

0 0 1

解析

假如一个方格内的水能够留到外面去,这个方格中就不会有积水。水往低处流,将每个方格视为一个点,往四周比自己低的点连边,边权为两个高度的最大值。将城外单独作为一点,往所有在边界的点连边。由木桶原理,一个水池的高度一定由边缘高度最小的点决定。那么,一个点的高度会由到边界外的路径中经过的边权最大值最小的路径决定,记这个最大值为b。这样的路径一定是图的最小生成树上到城外点的路径。由此,我们得到如下算法:

连边构图完成后,将图的最小生成树求出来,在树上求城外点到每个点的路径上的最大值b,最后的答案即为\(b-a[i][j]\)。

代码

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#define N 302
using namespace std;
struct node{
int u,v,w;
}e[N*N*4];
int p[4]={1,-1,0,0},q[4]={0,0,1,-1};
int head[N*N],ver[N*N*4],nxt[N*N*4],edge[N*N*4],l,tot;
int n,m,i,j,k,a[N][N],id[N][N],cnt,fa[N*N],dis[N*N];
bool in(int x,int y)
{
return x<=n&&x>=1&&y<=m&&y>=1;
}
void insert(int x,int y,int z)
{
l++;
ver[l]=y;
edge[l]=z;
nxt[l]=head[x];
head[x]=l;
}
int my_comp(const node &x,const node &y)
{
return x.w<y.w;
}
int find(int x)
{
if(fa[x]!=x) fa[x]=find(fa[x]);
return fa[x];
}
void Kruscal()
{
sort(e+1,e+tot+1,my_comp);
for(i=1;i<=n*m;i++) fa[i]=i;
int cnt=n*m+1;
for(int i=1;i<=tot;i++){
if(cnt==1) break;
int f1=find(e[i].u),f2=find(e[i].v);
if(f1!=f2){
insert(e[i].u,e[i].v,e[i].w);
insert(e[i].v,e[i].u,e[i].w);
fa[f1]=f2;
cnt--;
}
}
}
void dfs(int x,int pre)
{
for(int i=head[x];i!=-1;i=nxt[i]){
int y=ver[i];
if(y!=pre){
dis[y]=max(dis[x],edge[i]);
dfs(y,x);
}
}
}
int main()
{
freopen("water.in","r",stdin);
freopen("water.out","w",stdout);
cin>>n>>m;
for(i=1;i<=n;i++){
for(j=1;j<=m;j++){
cin>>a[i][j];
id[i][j]=++cnt;
}
}
for(i=1;i<=n;i++){
for(j=1;j<=m;j++){
if(i==1||i==n||j==1||j==m) e[++tot]=(node){0,id[i][j],max(0,a[i][j])};
for(k=0;k<4;k++){
int x=i+p[k],y=j+q[k];
if(in(x,y)&&a[x][y]<=a[i][j]) e[++tot]=(node){id[x][y],id[i][j],max(a[x][y],a[i][j])};
}
}
}
memset(head,-1,sizeof(head));
Kruscal();
dfs(0,0);
cnt=0;
for(i=1;i<=n;i++){
for(j=1;j<=m;j++){
cnt++;
cout<<dis[cnt]-a[i][j]<<' ';
}
cout<<endl;
}
fclose(stdin);
fclose(stdout);
return 0;
}

Test 6.24 T3 水题的更多相关文章

  1. cdoj 24 8球胜负(eight) 水题

    8球胜负(eight) Time Limit: 20 Sec  Memory Limit: 256 MB 题目连接 http://acm.uestc.edu.cn/#/problem/show/24 ...

  2. [poj2247] Humble Numbers (DP水题)

    DP 水题 Description A number whose only prime factors are 2,3,5 or 7 is called a humble number. The se ...

  3. gdutcode 1195: 相信我这是水题 GDUT中有个风云人物pigofzhou,是冰点奇迹队的主代码手,

    1195: 相信我这是水题 Time Limit: 1 Sec  Memory Limit: 128 MBSubmit: 821  Solved: 219 Description GDUT中有个风云人 ...

  4. hdu 2041:超级楼梯(水题,递归)

    超级楼梯 Time Limit: / MS (Java/Others) Memory Limit: / K (Java/Others) Total Submission(s): Accepted Su ...

  5. Educational Codeforces Round 7 B. The Time 水题

    B. The Time 题目连接: http://www.codeforces.com/contest/622/problem/B Description You are given the curr ...

  6. CYJian的水题大赛

    实在没忍住就去打比赛了然后一耗就是一天 最后Rank19还是挺好的(要不是乐多赛不然炸飞),这是唯一一套在Luogu上号称水题大赛的而实际上真的是水题大赛的比赛 好了我们开始看题 T1 八百标兵奔北坡 ...

  7. 【转】POJ百道水题列表

    以下是poj百道水题,新手可以考虑从这里刷起 搜索1002 Fire Net1004 Anagrams by Stack1005 Jugs1008 Gnome Tetravex1091 Knight ...

  8. HDU - 1716 排列2 水题

    排列2 Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submis ...

  9. HDU--Elevator(水题)

    Elevator nid=24#time"> Time Limit: 1000ms   Memory limit: 32768K  有疑问?点这里^_^ 题目描写叙述 The high ...

随机推荐

  1. vmware 虚拟 CPU 性能计数器事件与主机 CPU 不兼容。

    错误提示:虚拟 CPU 性能计数器事件与主机 CPU 不兼容. 点放弃 如果是暂时状态选关机, 丢失掉运行状态,即可保留硬盘内容重新开机

  2. Netty 系列之 Netty 高性能之道 高性能的三个主题 Netty使得开发者能够轻松地接受大量打开的套接字 Java 序列化

    Netty系列之Netty高性能之道 https://www.infoq.cn/article/netty-high-performance 李林锋 2014 年 5 月 29 日 话题:性能调优语言 ...

  3. Gradel 多渠道打包 代码混淆

    http://blog.csdn.net/ttccaaa/article/details/47687241 http://www.bubuko.com/infodetail-987756.html h ...

  4. Sqlserver 中间表的操作

    去除列名重复 select rtrim(ltrim(a.Bank)) as Country, count(*) as Total from T_BASE_OWNER a left join T_BAS ...

  5. 阶段1 语言基础+高级_1-3-Java语言高级_04-集合_07 Collections工具类_1_Collections集合工具类的方法

    这是一个个的添加的方式 参数是个可变的元素.可以传递任意多的元素 shuffle打乱集合元素顺序

  6. delphi SetWindowPos改变窗体位置和状态

    http://blog.163.com/yuanliaofan@126/blog/static/1730690722012534428814/ delphi SetWindowPos改变窗体位置和状态 ...

  7. KETTLE——(例)简单的字段转换

    一个简单的小例子:结合数据抽取.简单的字段转换.数据输出. 资源库连接.数据输入.数据输出.参见之前的文章. ​ 基本的转换结构是这样的,我们从表中输入,选择我们需要的字段,已经对应的名称,然后将数据 ...

  8. JS-在本页面禁止页面返回

    这个问题是最近遇到的 解决方案我百度的并测试有效 // 如果你希望用户不用有返回功能 可缩写如下 或使用location.replace('url')跳转链接 history.pushState(nu ...

  9. Mac019--Ubuntu上安装Rancher

    首先安装:VisualBox虚拟机. 下载:ubuntu镜像 (ubuntu基于linux的免费开源桌面PC操作系统) ======================================== ...

  10. js 获取屏幕宽高

    网页可见区域宽: document.body.clientWidth 网页可见区域高: document.body.clientHeight 网页可见区域宽: document.body.offset ...