BZOJ 4242: 水壶 Kruskal+BFS
4242: 水壶
Time Limit: 40 Sec Memory Limit: 256 MB
Submit: 427 Solved: 112
[Submit][Status][Discuss]
Description
Input
Output
Sample Input
.....
..##.
.#...
..#..
.....
1 1
4 2
3 3
2 5
1 2
2 4
1 3
3 4
Sample Output
4
4
2
HINT
Source
JOI 2013~2014 春季training合宿 竞技2 By PoPoQQQ
朴素的暴力:得到任意两点的间的最短距离,然后kruskal。因为是求最大值,所以可以直接用并查集(按秩合并)上的路径最值。树高为O(logP)。共O(P*W*H)
考虑慢慢增加每个建筑物连出去的边权,这个和Kruskal很相似。然后又一个朴素的想法,搞P个队列,同时扩展。碰到一个建筑物才停下来并不扩展这个建筑物,合并这个两个建筑物。O(P*W*H)
既然是同时扩展,那么边权肯定都一样。那么碰到一个已经被扩展的点就可以将距离加起来,用来更新当成这个两个建筑物的距离。边权都*2肯定还是满足kruskal的算法。一个点最多被碰四次。O(W*H*4)
细节:可能边权并没有*2,而是一个奇一个偶,可能会影响同一种边权的kruskal加边顺序,所以我把这些边都存下来......
然后求一发Kruskal就可以了。
#include<cstdio>
#include<cstring>
#include<algorithm> const int HW(),len(),N();
const int dx[]={,,-,};
const int dy[]={-,,,};
int O[HW][HW],last[HW][HW],dis[HW][HW],H,W,P,Q;
struct Palce{int x,y;}q[N+],now; int l,h;
char ch[HW];int x,y;
struct Node{int a,b,c;}bot[N+];int top;
int f[len+],cost[len+],rank[len+],depth[len+]; bool cmp(Node A,Node B){return A.c<B.c;}
int max(int a,int b){return a>b?a:b;}
template <class T>void read(T &x)
{
x=;int f=; char ch=getchar();
while(ch<''||ch>''){f=(ch=='-');ch=getchar();}
while(ch>=''&&ch<=''){x=x*+ch-'';ch=getchar();}
x=f?-x:x;
} int gf(int x){return x==f[x]?x:gf(f[x]);}
int gf_d(int x)
{
int d; for(d=;x!=f[x];x=f[x])d++;
return d;
}
void swap(int &a,int &b){if(a==b)return;a^=b;b^=a;a^=b;}
void union_fa(int x,int y,int d)
{
x=gf(x),y=gf(y); if(x==y)return;
if(rank[x]>rank[y]) swap(x,y);
if(rank[x]==rank[y]) rank[y]++;
f[x]=y; cost[x]=d;
}
void BFS()
{
h=;
while(h<l)
{
now=q[++h];
for(int d=;d<;d++)
if(O[now.x+dx[d]][now.y+dy[d]])
{
if(last[now.x+dx[d]][now.y+dy[d]]&&last[now.x+dx[d]][now.y+dy[d]]!=last[now.x][now.y])
bot[++top]=(Node){last[now.x+dx[d]][now.y+dy[d]],last[now.x][now.y],dis[now.x+dx[d]][now.y+dy[d]]+dis[now.x][now.y]};
else
if(!dis[now.x+dx[d]][now.y+dy[d]])
{
dis[now.x+dx[d]][now.y+dy[d]]=dis[now.x][now.y]+;
last[now.x+dx[d]][now.y+dy[d]]=last[now.x][now.y];
q[++l]=(Palce){now.x+dx[d],now.y+dy[d]};
}
}
}
}
int jump(int x,int y)
{
int d=;
if(depth[x]<depth[y])swap(x,y);
for(;depth[x]!=depth[y];)d=max(d,cost[x]),x=f[x];
for(;x!=y;)d=max(d,cost[x]),d=max(d,cost[y]),x=f[x],y=f[y];
return d;
}
int main()
{
// freopen("C.in","r",stdin);
// freopen("C.out","w",stdout);
read(H),read(W);
read(P),read(Q);
for(int i=;i<=H;i++)
{
scanf("%s",ch+);
for(int j=;j<=W;j++)O[i][j]=(ch[j]!='#');
}
for(int i=;i<=P;i++)
{
read(x),read(y); f[i]=i; rank[i]=;
last[x][y]=i; q[++l]=(Palce){x,y};
}
BFS();//O(H*W)
std::sort(bot+,bot++top,cmp);
for(int i=;i<=top;i++)
union_fa(bot[i].a,bot[i].b,bot[i].c);//按kruskal走,那么两个连通块之间的过往最大值就是这条边,所以可以直接在并查集的树上求最值。
for(int i=;i<=P;i++)depth[i]=gf_d(i);//O(PlogP)
for(int i=;i<=Q;i++)
{
read(x);read(y);
if(gf(x)!=gf(y))printf("-1\n");
else printf("%d\n",jump(x,y));//O(logP)
}
return ;
}
BZOJ 4242: 水壶 Kruskal+BFS的更多相关文章
- bzoj 4242 水壶 (多源最短路+最小生成树+启发式合并)
4242: 水壶 Time Limit: 50 Sec Memory Limit: 512 MBSubmit: 1028 Solved: 261[Submit][Status][Discuss] ...
- BZOJ 4242: 水壶(Kruskal重构树 + Bfs)
题意 一块 \(h ∗ w\) 的区域,存在障碍.空地.\(n\) 个建筑,从一个建筑到另一个建筑的花费为:路径上最长的连续空地的长度. \(q\) 次询问:从建筑 \(s_i\) 到 \(t_i\) ...
- BZOJ 4242 水壶(BFS建图+最小生成树+树上倍增)
题意 JOI君所居住的IOI市以一年四季都十分炎热著称. IOI市是一个被分成纵H*横W块区域的长方形,每个区域都是建筑物.原野.墙壁之一.建筑物的区域有P个,编号为1...P. JOI君只能进入建筑 ...
- BFS+最小生成树+倍增+LCA【bzoj】4242 水壶
[bzoj4242 水壶] Description JOI君所居住的IOI市以一年四季都十分炎热著称. IOI市是一个被分成纵H*横W块区域的长方形,每个区域都是建筑物.原野.墙壁之一.建筑物的区域有 ...
- 水壶-[Kruskal重构树] [解题报告]
水壶 本来从不写针对某题的题解,但因为自己实在是太蠢了,这道题也神TM的恶心,于是就写篇博客纪念一下 H水壶 时间限制 : 50000 MS 空间限制 : 565536 KB 评测说明 : 2s,51 ...
- BZOJ 1086 王室联邦 | BFS
BZOJ 1086 王室联邦 题意 把一棵树分块,每块大小在[B, 3B]之间(B由输入数据给出),每个块需要对应一个核心点,核心点可以在块内,这个点要满足块内每个点到核心点的路径上的点都属于这个块( ...
- [bzoj 3732] Network (Kruskal重构树)
kruskal重构树 Description 给你N个点的无向图 (1 <= N <= 15,000),记为:1-N. 图中有M条边 (1 <= M <= 30,000) ,第 ...
- bzoj 1098 poi2007 办公楼 bfs+链表
题意很好理解,求给出图反图的联通块个数. 考虑这样一个事情:一个联通块里的点,最多只会被遍历一次,再遍历时没有任何意义 所以用链表来存,每遍历到一个点就将该点删掉 #include<cstdio ...
- BZOJ 1295 最长距离 BFS+枚举
题目链接: https://www.lydsy.com/JudgeOnline/problem.php?id=1295 题目大意: windy有一块矩形土地,被分为 N*M 块 1*1 的小格子. 有 ...
随机推荐
- MySQL之创、增、删、改、查
MySQL Select version(); 当前服务器版本 Select database(); 查看当前工作数据库 Show databases; 显示所有数据库 Select user ...
- 附近wifi都是你的
今天给大家介绍deauth攻击. 最终效果:附近你指定的任何wifi,别人都无法连接,即便连接上的也会断掉. 由于我在 “世界虽大,但没有破不了的wifi” 这篇文章中写的很详细,所以我在这里就步详 ...
- Android开发中,那些让你觉得相见恨晚的方法、类或接口
Throwable类中的getStackTrace()方法,根据这个方法可以得到函数的逐层调用地址,其返回值为StackTraceElement[],而在StackTraceElement类中有四个方 ...
- JQ 获取ul\ol 下面li的个数
使用 jQuery 获取 ul 下面 li 的个数,那么我们需要遍历我们的ul.如果你的ul有class .id 或两者都没,您可以使用 ul 标签来遍历. //遍历ul 获取li个数 $(" ...
- MS SQL JSON类型type
在MS SQL Server 2016,已经支持JSON处理. 执行下面代码,将获取ms sql server对象类型以及其说明: IF OBJECT_ID('tempdb.dbo.#json_typ ...
- 使用Maven构建Spring Security应用
1.概述 本文将解释如何使用Maven构建Spring Security应用程序.将讨论使用Spring Security依赖项的特定用例.最新的Spring Security版本可以在Maven C ...
- 用js判断屏幕的宽度,改变html字体大小用rem布局
if (document.documentElement.clientWidth > 600) {//页面宽度大于600px让其宽度等于600px,字体大小等于60px,居中 document. ...
- Litjson
http://www.cnblogs.com/peiandsky/archive/2012/04/20/2459219.html JSON(JavaScript Object Notation) 是一 ...
- IT兄弟连 JavaWeb教程 过滤器2
3 多个过滤器的执行顺序 如果一个Web应用中使用一个过滤器不能解决实际中的业务需要,那么可以部署多个过滤器对业务请求进行多次处理,这样做就组成了一个过滤器链.Web服务器在处理过滤器链时,将按过滤 ...
- 剑指Offer的学习笔记(C#篇)-- 链表中倒数第K个点
题目描述 输入一个链表,输出该链表中倒数第k个结点. 一 . 数据结构基础概念普及(线性表). 线性表可分为顺序表与链表,它们是堆栈.队列.树.图等数据结构的实现基础. 顺序表,线性表的顺序存储结构是 ...