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 的小格子. 有 ...
随机推荐
- <c和指针>学习笔记3之操作符,表达式与指针
1 操作符 (1)移位操作符 左移<<:值最左边的几位丢弃,右边多出来的几个空位用0补齐 01101101 011(丢弃)01101000(后面三位补0) 右移>>: 算术左移 ...
- 2-1 本章作业&2-2 开发系统与工具选择
2-1 2-2 推荐使用Android Studio开发Flutter
- Spring入门第十一课
IOC容器中Bean的生命周期 Spring IOC容器可以管理Bean的生命周期,Spring允许在Bean生命周期的特定点执行定制的任务. Spring IOC容器对Bean的生命周期进行管理的过 ...
- rest framework 认证
一.简单认证示例 需求: 用户名密码正确:没有 token 则产生一个 token,有 token 则更新,返回登录成功: 若用户名或密码错误,返回错误信息. 1.models.py from dja ...
- 将Gridview导出到Excel
GridViewToExcel(EdceExcelGV, "application/ms-exce","xxxxxx表"); protected void Gr ...
- 前端需要了解的http知识
一.五层协议1. OSI(Open System Interconnection 开放式系统互联)七层协议 1)应用层 2)表示层 3)会话层 4)传输层 5)网络层 6)数据链接层 7)物理层2. ...
- ThinkSNS+ 是如何计算字符显示长度的
什么是ThinkSNS+ ThinkSNS(简称TS),一款全平台综合性社交系统,目前最新版本为ThinkSNS+.ThinkSNS V4 ThinkSNS[简]. 今天我们来聊一下可能很多人都会头疼 ...
- 12pm 究竟是中午还是午夜
12pm是中午=12noon12am是午夜=12midnightMN-midnight(午夜,中午) AM是after midnight开头字母 PM是prior to midnight开头字母正中午 ...
- 搞定C系语言的的swap
http://www.cs.utsa.edu/~wagner/CS2213/swap/swap.html 原地址 Parameters, by value and by reference: Both ...
- 12.创建高级联结---SQL
一.使用表别名 SQL除了可以对列名和计算字段使用别名,还允许给表名起别名.这样做有两个主要理由: 缩短SQL语句: 允许在一条SELECT语句中多次使用相同的表. SELECT cust_name, ...