CDOJ 203 并查集+优先队列 好题
Islands
Time Limit: 30000/10000MS (Java/Others) Memory Limit: 65535/65535KB (Java/Others)
Deep in the Carribean, there is an island even stranger than the Monkey Island, dwelled by Horatio Torquemada Marley. Not only it has a rectangular shape, but is also divided into an n×mn×m grid. Each grid field has a certain height. Unfortunately, the sea level started to raise and in year ii, the level is ii meters. Another strange feature of the island is that it is made of sponge, and the water can freely flow through it. Thus, a grid field whose height is at most the current sea level is considered flooded.Adjacent unflooded fields (i.e., sharing common edge) create unflooded areas. Sailors are interested in the number of unflooded areas in a given year.
An example of a 4×54×5 island is given below. Numbers denote the heights of respective fields in meters.Unflooded fields are darker; there are two unflooded areas in the first year and three areas in the second year.

Input
Multiple Test Cases
The input contains several test cases. The first line of the input contains a positive integer Z≤20Z≤20,denoting the number of test cases. Then ZZ test cases follow, each conforming to the format described in section Single Instance Input. For each test case, your program has to write an output conforming to the format described in section Single Instance Output.
Single Instance Input
The first line contains two numbers nn and mm separated by a single space, the dimensions of the island, where 1≤n,m≤10001≤n,m≤1000. Next nn lines contain mm integers from the range [1,109][1,109] separated by single spaces, denoting the heights of the respective fields. Next line contains an integer TT (1≤T≤1051≤T≤105). The last line contains TT integers tjtj , separated by single spaces, such that 0≤t1≤t2≤⋯≤tT≤1090≤t1≤t2≤⋯≤tT≤109
Output
Single Instance Output
Your program should output a single line consisting of TT numbers rjrj , where rjrj is the number of unflooded areas in year tjtj . After every number ,you must output a single space!
Sample input and output
| Sample Input | Sample Output |
|---|---|
1 |
2 3 1 0 0 |
Source
题目大意:有一个岛屿是n*m的长方形的,每个格子的高度会给定,然后这个地方的水位会逐年上涨,在第i年时水位是i。就是说,所有高度<=i的格子都会被淹没。求没有被淹没的区域有几块(如果两个格子有公共边就认为它们属于同一个区域)。
现在给出n和m(1<=n,m<=1000),以及每个格子的高度([1,10^9]),然后有T([1,10^5])次查询,再给出t1,t2,,,(0,10^9),对于ti保证t这个序列是上升的。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <vector>
#include <queue>
#include <stack>
#include <map>
#include <algorithm>
#include <set>
using namespace std;
typedef long long ll;
typedef unsigned long long Ull;
#define MM(a,b) memset(a,b,sizeof(a));
const double eps = 1e-10;
const int inf = 0x3f3f3f3f;
const double pi=acos(-1);
const int maxn=1000;
int t[100000+10],ans[100000+10];
int dx[5]={-1,1,0,0};
int dy[5]={0,0,1,-1};
int n,m; struct node{
int x,y,h,id;
bool operator<(const node b) const
{
return this->h<b.h;//逆序考虑
}
}ne[maxn*maxn+10];
int par[maxn*maxn+10]; int findr(int id)
{
if(par[id]!=id)
par[id]=findr(par[id]);
return par[id];
} void unite(int i,int j)
{
int ri=findr(i);
int rj=findr(j);
if(ri!=rj) par[ri]=rj;
} int inmap(int x,int y)
{
return x>=1&&x<=n&&y>=1&&y<=m;
} priority_queue<node> q;//元素多了的话优先队列还是要开到外面的
int main()
{
int cas;
scanf("%d",&cas);
while(cas--)
{
MM(ans,0);
scanf("%d %d",&n,&m);
int sz=0;
while(q.size()) q.pop();//清空 for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
{
scanf("%d",&ne[++sz].h);
ne[sz].x=i;
ne[sz].y=j;
ne[sz].id=(i-1)*m+j;
par[sz]=ne[sz].id;
q.push(ne[sz]);
}
int w;
scanf("%d",&w);
for(int i=1;i<=w;i++) scanf("%d",&t[i]); for(int k=w;k>=1;k--)
{
ans[k]=ans[k+1];//当前集合在后一时刻的基础上
while(q.size())
{
node cur=q.top();
if(cur.h<=t[k]) break;
q.pop();
ans[k]++;//每个节点刚出现时都是一个独立的 for(int i=0;i<=3;i++)
{
int x=cur.x+dx[i];
int y=cur.y+dy[i];
int id=(x-1)*m+y;
if(ne[id].h<=t[k]||!inmap(x,y)) continue; int rx=findr(cur.id);//因为cur的父节点会随着合并而更新,所以需 //要再搜索一次
int ry=findr(id);
if(rx!=ry)
{
unite(rx,ry);
ans[k]--;//可以进行合并的话,集合数减1
}
}
}
}
for(int i=1;i<=w;i++)
printf("%d ",ans[i]);
printf("\n");
}
return 0;
}
分析:并查集神题啊,暴搜肯定超时的,因为下一个时间的集合数是肯定在这一个时刻的集合的基础上减少的,所以可以考虑并查集,但是并查集是进行连接点的而不是删除点的,怎么办呢?把时间反过来逆向思考就好,最后还要注意,每次进行集合间的合并后,下次再用到该点时还要再查找一次。
其实可以用图来理解,每一个节点刚开始都是独立的,故增1,然后每一次合并时相当于连接了一条边,
集合数就会减1,因此一个集合最终只会增1,当然,如果已经在同一个集合的话就不能进行连接了,因为
不能产生环;
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <vector>
#include <queue>
#include <stack>
#include <map>
#include <algorithm>
#include <set>
using namespace std;
typedef long long ll;
typedef unsigned long long Ull;
#define MM(a,b) memset(a,b,sizeof(a));
const double eps = 1e-;
const int inf = 0x3f3f3f3f;
const double pi=acos(-);
const int maxn=;
int t[+],ans[+];
int dx[]={-,,,};
int dy[]={,,,-};
int n,m; struct node{
int x,y,h,id;
bool operator<(const node b) const
{
return this->h<b.h;
}
}ne[maxn*maxn+];
int par[maxn*maxn+]; int findr(int id)
{
if(par[id]!=id)
par[id]=findr(par[id]);
return par[id];
} void unite(int i,int j)
{
int ri=findr(i);
int rj=findr(j);
if(ri!=rj) par[ri]=rj;
} int main()
{
int cas;
scanf("%d",&cas);
while(cas--)
{
scanf("%d %d",&n,&m);
int sz=;
priority_queue<node> q;
for(int i=;i<=n;i++)
for(int j=;j<=m;j++)
{
scanf("%d",&ne[++sz].h);
ne[sz].x=i;
ne[sz].y=j;
ne[sz].id=(i-)*m+j;
par[sz]=-;
q.push(ne[sz]);
}
int w;
scanf("%d",&w);
for(int i=;i<=w;i++) scanf("%d",&t[i]); for(int k=w;k>=;k--)
{
ans[k]=ans[k+];
while()
{
node cur=q.top();
if(cur.h<=t[k]) break;
q.pop();
if(par[cur.id]==-)
{
ans[k]++;
par[cur.id]=cur.id;
} int rx=findr(cur.id);
for(int i=;i<=;i++)
{
int x=cur.x+dx[i];
int y=cur.y+dy[i];
int id=(x-)*m+y;
int ry=findr(id);
if(ne[id].h<=t[i]) continue;
if(par[id]==-) ans[k]++;
if(rx!=ry)
{
unite(rx,ry);
ans[k]--;
}
}
}
}
for(int i=;i<=w;i++)
printf("%d ",ans[i]);
}
return ;
}
CDOJ 203 并查集+优先队列 好题的更多相关文章
- poj 2236:Wireless Network(并查集,提高题)
Wireless Network Time Limit: 10000MS Memory Limit: 65536K Total Submissions: 16065 Accepted: 677 ...
- poj 2524:Ubiquitous Religions(并查集,入门题)
Ubiquitous Religions Time Limit: 5000MS Memory Limit: 65536K Total Submissions: 23997 Accepted: ...
- poj 1611:The Suspects(并查集,经典题)
The Suspects Time Limit: 1000MS Memory Limit: 20000K Total Submissions: 21472 Accepted: 10393 De ...
- hrbustoj 1073:病毒(并查集,入门题)
病毒Time Limit: 1000 MS Memory Limit: 65536 KTotal Submit: 719(185 users) Total Accepted: 247(163 user ...
- 并查集+优先队列+启发式合并 || 罗马游戏 || BZOJ 1455 || Luogu p2713
题面:P2713 罗马游戏 题解: 超级大水题啊,特别水.. 并查集维护每个人在哪个团里,优先队列维护每个团最低分和最低分是哪位,然后每次判断一下哪些人死了,随便写写就行 并查集在Merge时可以用启 ...
- “玲珑杯”ACM比赛 Round #7 B -- Capture(并查集+优先队列)
题意:初始时有个首都1,有n个操作 +V表示有一个新的城市连接到了V号城市 -V表示V号城市断开了连接,同时V的子城市也会断开连接 每次输出在每次操作后到首都1距离最远的城市编号,多个距离相同输出编号 ...
- Codeforces Round #212 (Div. 2) D. Fools and Foolproof Roads 并查集+优先队列
D. Fools and Foolproof Roads You must have heard all about the Foolland on your Geography lessons. ...
- Intel Code Challenge Elimination Round (Div.1 + Div.2, combined) A B C D 水 模拟 并查集 优先队列
A. Broken Clock time limit per test 1 second memory limit per test 256 megabytes input standard inpu ...
- 并查集基础 模板题 hdu1232 畅通工程
模板题 引入并查集——一则有趣的故事 为了解释并查集的原理,我将举一个更有趣的例子.话说江湖上散落着各式各样的大侠,有上千个之多.他们没有什么正当职业,整天背着剑在外面走来走去,碰到和自己不是一路人的 ...
随机推荐
- poj 1061 青蛙的约会+拓展欧几里得+题解
青蛙的约会+拓展欧几里得+题解 纵有疾风起 题意 两只青蛙在网上相识了,它们聊得很开心,于是觉得很有必要见一面.它们很高兴地发现它们住在同一条纬度线上,于是它们约定各自朝西跳,直到碰面为止.可是它们出 ...
- Python文件的几种读写方式
1). "w "写模式,它是不能读的,如果用w模式打开一个已经存在的文件,会清空以前的文件内容,重新写 "w+ "是读写内容,只要沾上w,肯定会清空原来的文件2 ...
- python with hadoop
python with hdfs hdfs 可以在 linux 本地操作 bin/hdfs dfs -ls /foo 但是这种只能在 命令行 操作. 通常我们需要在程序中实现远程操作,python ...
- CentOS6.6安装使用MyCat
https://blog.csdn.net/u012948302/article/details/78902092 1. 安装Java环境MyCAT 是使用 JAVA 语言进行编写开发,使用前需要先安 ...
- 【转载】Django自带的注册登陆功能
1.登陆 知识点: a.auth.authenticate(username=name值, password=password值) 验证用户名和密码 b.auth.login(request, use ...
- 7.利用canvas和js画一个渐变的
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title> ...
- 关于在docker中配置elasticsearch容器的方法
一.关于docker的安装,注意几点 1.如果系统是Win10家庭版,是没有Hyper-V的,所以无法安装docker(运行docker安装包会报错),为此docker官网提供的解决方法是安装dock ...
- 69. Sqrt(x) (JAVA)
Implement int sqrt(int x). Compute and return the square root of x, where x is guaranteed to be a no ...
- Scala Option 从官方DOC解析
Represents optional values. Instances of Option are either an instance of scala.Some or the object N ...
- linux的安全--Selinux,tcp_wrappers,iptables使用
一.linux安全 安全主要是端口与服务的对应配置 1.1 linux安全主要通过下面三个进行加固 Selinux----主要是对内核的访问权限加以控制 tcp_wrappers---一定程度上限制某 ...