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 的小格子. 有 ...
随机推荐
- 【机器学习】k近邻算法(kNN)
一.写在前面 本系列是对之前机器学习笔记的一个总结,这里只针对最基础的经典机器学习算法,对其本身的要点进行笔记总结,具体到算法的详细过程可以参见其他参考资料和书籍,这里顺便推荐一下Machine Le ...
- 二十五种网页加速方法和seo优化技巧
一.使用良好的结构 可扩展 HTML (XHTML) 具有许多优势,但是其缺点也很明显.XHTML 可能使您的页面更加符合标准,但是它大量使用标记(强制性的 <start> 和 <e ...
- ue4 改c++类名
http://blog.csdn.net/chinahaerbin/article/details/50855135
- Docker 安装部署RabbitMQ
获查询镜像 docker search rabbitmq:management 可以看到如下结果: 获取镜像 docker pull rabbitmq:management 运行镜像 docker r ...
- python 合并两个文件并将合并内容保存在另一个文件中
简单地文件合并方法 思路如下: 分别读取两个文件中的内容,并将其保存在一个列表中,将列表通过join()函数转为字符,并将新字符保存在新的文件中. 其中,test1.txt中的内容为: test2.t ...
- transition动画最简使用方式
HTML <a href="#" title="">test</a> CSS a {display:block; width:200px ...
- p标签间距问题
用<p></p>标签写文本时,控制行与行之间的高度最好用line-height,不要用margin或padding: 因为P标签本身就带有一定的上下间距,且自带的间距在模拟 ...
- 3、CreateJS介绍-SoundJS
需要在html5文件中引入的CreateJS库文件是soundjs-0.5.2.min.js HTML5文件如下: <!DOCTYPE html> <html lang=" ...
- [題解](水/數學)luogu_P1147連續自然數和
尺取法a掉 然而數學解法為 等差數列求和公式: sum(L,R)=(L+R)(R-L+1)/2=M 即(L+R)(R-L+1)=2M 可以把2M分解成两个数之积,假设分成了两个数K1,K2,且K1&l ...
- oralce9i部署安装
为什么还学习oracle9i,因为目前大多数企业的数据依然存储在oracle9i上面,对于数据升级存在很大风险,因此在学习oralce之前,首先熟悉oracle9i也是很有必要的.现在我们先来学习or ...