###[水壶](http://oi.nks.edu.cn/zh/Problem/Details?cid=222&tid=H)
####本来从不写针对某题的题解,但因为自己实在是太蠢了,这道题也神TM的恶心,于是就写篇博客纪念一下


H水壶
时间限制 : 50000 MS 空间限制 : 565536 KB 评测说明 : 2s,512m
问题描述

\(JOI\)君所居住的IOI市以一年四季都十分炎热著称。

\(IOI\)市是一个被分成\(H*W\)块区域的长方形,每个区域都是建筑物、原野、墙壁之一。建筑物的区域有\(P\)个,编号为\(1...P\)。

$ JOI$君只能进入建筑物与原野,而且每次只能走到相邻的区域中,且不能移动到市外。

\(JOI\)君因为各种各样的事情,必须在各个建筑物之间往返。虽然建筑物中的冷气设备非常好,但原野上的日光十分强烈,因此在原野上每走过一个区域都需要\(1\)单位的水。此外,原野上没有诸如自动售货机、饮水处之类的东西,因此\(IOI\)市的市民一般都携带水壶出行。大小为\(x\)的水壶最多可以装\(x\)单位的水,建筑物里有自来水可以将水壶装满。

由于携带大水壶是一件很困难的事情,因此\(JOI\)君决定携带尽量小的水壶移动。因此,为了随时能在建筑物之间移动,请你帮他写一个程序来计算最少需要多大的水壶。

现在给出\(IOI\)市的地图和\(Q\)个询问,第i个询问\((1<=i<=Q)\)为“在建筑物\(S_i\)和\(T_i\)之间移动,最小需要多大的水壶?”,请你对于每个询问输出对应的答案。

输入格式

第一行四个空格分隔的整数\(H,W,P,Q\),表示\(IOI\)市被分成了纵\(H*W\)块区域,有\(P\)个建筑物,\(Q\)次询问。

接下来\(H\)行,第\(i\)行\((1<=i<=H)\)有一个长度为\(W\)的字符串,每个字符都是’.’或’#’之一,\(’.’\)表示这个位置是建筑物或原野,’#’表示这个位置是墙壁。

接下来\(P\)行描述\(IOI\)市每个建筑物的位置,第\(i\)行\((1<=i<=P)\)有两个空格分隔的整数\(Ai\)和\(Bi\),表示第i个建筑物的位置在第\(A_i\)行第\(B_i\)列。保证这个位置在地图中是’.’

接下来\(Q\)行,第\(i\)行\((1<=i<=Q)\)有两个空格分隔的整数\(S_i\)和\(T_i\),表示第\(i\)个询问为“在建筑物\(Si\)和\(Ti\)之间移动,最小需要多大的水壶?”

输出格式

输出\(Q\)行,第\(i\)行\((1<=i<=Q)\)一个整数,表示在建筑物\(S_i\)和\(T_i\)之间移动最小需要多大的水壶。 如果无法到达,输出\(-1\)。此外,如果不需要经过原野就能到达,输出\(0\)。

样例输入

5 5 4 4

.....

..##.

.#...

..#..

.....

1 1

4 2

3 3

2 5

1 2

2 4

1 3

3 4

样例输出

3

4

4

2

提示

\(1<=H<=2000\)

\(1<=W<=2000\)

\(2<=P<=2*10^5\)

\(1<=Q<=2*10^5\)

\(1<=A_i<=H(1<=i<=P)\)

\(1<=B_i<=W(1<=i<=P)\)

\((A_i,B_i)≠(A_j,B_j)(1<=i<j<=P)\)

\(1<=S_i<T_i<=P(1<=i<=Q)\)


题解

很显然这道题的询问类似于\(NOIP2015\)运输计划(不知道是不是这年的题啊),我们可以轻松愉快的使用\(Kruskal\)重构树或者很棒很棒的直接倍增记录;

但是这个方格图就很恶心,我们需要自己建一个仅有我们所需建筑的点和链接他们的边的图出来,这可咋整?

这就是这道题较为恶心的地方,我们可以对每一块染色,每当我们到达一个已被其他颜色染色的合法区域,把这条边就可以加入我们的存边数组,不知道开多大,就用\(Vector\)来存储;

但其实这并不是恶心我的地方\(,,,\),恶心的是\(LCA\)居然写错,\(WA,MLE\)到天上了简直惨死,下次再在写\(Kruskal\)重构树求\(LCA\)时把\(log_[tot]\)开成\(log_[n]\)就原地自爆,更别提写LCA写成Del=dep[x]-dep[x];


\(code:\)
#include<cstdio>
#include<algorithm>
#include<ctype.h>
#include<vector>
#include<queue>
#include<cstring>
#define lowbit(x) (x&-x)
#define ll long long
#define ld double
#include<map>
#include<stdlib.h>
#include<ctime>
#define mod 19260817
using namespace std; char buf[1<<20],*p1,*p2;
inline char gc()
{
// return getchar();
return p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<20,stdin))==p1?0:*p1++;
} template<typename T>
inline void read(T &x)
{
char tt;
bool flag=0;
while(!isdigit(tt=gc())&&tt!='-');
tt=='-'?(flag=1,x=0):(x=tt-'0');
while(isdigit(tt=gc())) x=x*10+tt-'0';
if(flag) x=-x;
} const int maxn=200002;
struct node{
int x,y,len;
inline node(int a=0,int b=0,int c=0)
{x=a,y=b;len=c;}
inline bool operator<(node a)const
{return len>a.len;}
}; int n,m,p,que,tot;
int w[maxn<<1],fa[maxn<<1][20],dd[maxn<<1],dep[maxn<<1];
int log_[maxn<<1];
int book[2002][2002],dis[2002][2002];
int dx[4]={0,0,1,-1},dy[4]={1,-1,0,0};
char G[2002][2002];
vector<int>g[maxn<<1];
vector<node>a;
queue<node>q; int getfa(int x){
return x==dd[x]?x:dd[x]=getfa(dd[x]);
} void bfs()
{
for(int i=1;i<=p;i++)
{
int x,y;
read(x),read(y);
q.push(node(x,y));
book[x][y]=i;
}
while(!q.empty())
{
int id,x,y;
x=q.front().x,y=q.front().y;
id=book[x][y];q.pop();
for(int i=0;i<4;i++)
{
int tx=x+dx[i],ty=y+dy[i];
if(tx<=0||tx>n||ty<=0||ty>m||G[tx][ty]=='#'||book[tx][ty]==id) continue;
if(book[tx][ty])
a.push_back(node(id,book[tx][ty],dis[x][y]+dis[tx][ty]));
else
{
q.push(node(tx,ty));
dis[tx][ty]=dis[x][y]+1;
book[tx][ty]=id;
}
}
}
} void dfs(int x,int pre)
{
dep[x]=dep[pre]+1,fa[x][0]=pre;
for(int i=1;i<=log_[tot];i++)
if(fa[x][i-1]) fa[x][i]=fa[fa[x][i-1]][i-1];
else break; for(int i=g[x].size()-1;i>=0;i--)
{
int p=g[x][i];
if(p==pre) continue;
dfs(p,x);
}
} int query(int x,int y)
{
int fx=getfa(x),fy=getfa(y);
if(fx!=fy) return -1;
if(dep[x]<dep[y]) swap(x,y);
if(x==y) return 0;
int del=dep[x]-dep[y];
for(int i=log_[tot];i>=0;i--)
if(del>>i&1) x=fa[x][i];
if(x==y) return w[x];
for(int i=log_[n];i>=0;i--)
if(fa[x][i]!=fa[y][i]) x=fa[x][i],y=fa[y][i];
return w[fa[x][0]];
} int main()
{
read(n),read(m),read(p),read(que);
for(int i=1;i<=n;i++,gc())
for(int j=1;j<=m;j++)
G[i][j]=gc();tot=p;
bfs();
sort(a.begin(),a.end());log_[0]=-1;
for(int i=1;i<=p<<1;i++) dd[i]=i,log_[i]=log_[i>>1]+1;
for(int i=a.size()-1;i>=0;i--)
{
int fx=getfa(a[i].x),fy=getfa(a[i].y),len=a[i].len;;
if(fx==fy) continue;
dd[fx]=dd[fy]=++tot;
g[tot].push_back(fx);
g[tot].push_back(fy);
w[tot]=len;
}
for(int i=tot;i>=1;i--) if(!dep[i]) dfs(i,0);
while(que--)
{
int x,y;
read(x),read(y);
printf("%d\n",query(x,y));
}
}

找个时间填\(Kruskal\)重构树的坑\(ORZ,ORZ\)

水壶-[Kruskal重构树] [解题报告]的更多相关文章

  1. [jzoj 5926] [NOIP2018模拟10.25] naive 的图 解题报告(kruskal重构树+二维数点)

    题目链接: https://jzoj.net/senior/#main/show/5926 题目: 题解: 显然最小的最大路径在最小生成树上(最小生成树=最小瓶颈生成树) 于是我们建出kruskal重 ...

  2. [luogu P4197] Peaks 解题报告(在线:kruskal重构树+主席树 离线:主席树+线段树合并)

    题目链接: https://www.luogu.org/problemnew/show/P4197 题目: 在Bytemountains有N座山峰,每座山峰有他的高度$h_i$.有些山峰之间有双向道路 ...

  3. BZOJ 4242: 水壶(Kruskal重构树 + Bfs)

    题意 一块 \(h ∗ w\) 的区域,存在障碍.空地.\(n\) 个建筑,从一个建筑到另一个建筑的花费为:路径上最长的连续空地的长度. \(q\) 次询问:从建筑 \(s_i\) 到 \(t_i\) ...

  4. NOI2018归程(Kruskal重构树)

    题目描述 本题的故事发生在魔力之都,在这里我们将为你介绍一些必要的设定. 魔力之都可以抽象成一个 n 个节点.m 条边的无向连通图(节点的编号从 1 至 n). 我们依次用 l,a 描述一条边的长度. ...

  5. BZOJ 5415: [Noi2018]归程(kruskal重构树)

    解题思路 \(NOI2018\)的\(Day1\) \(T1\),当时打网络赛的时候不会做.学了一下\(kruskal\)重构树后发现问题迎刃而解了.根据\(kruskal\)的性质,如果要找从\(u ...

  6. AT4144-[ARC098D]Donation【Kruskal重构树,dp】

    正题 题目链接:https://www.luogu.com.cn/problem/AT4144 题目大意 \(n\)个点\(m\)条边的一张无向联通图,每个点有两个值\(a_i,b_i\).表示经过该 ...

  7. [bzoj 3732] Network (Kruskal重构树)

    kruskal重构树 Description 给你N个点的无向图 (1 <= N <= 15,000),记为:1-N. 图中有M条边 (1 <= M <= 30,000) ,第 ...

  8. 【BZOJ 3732】 Network Kruskal重构树+倍增LCA

    Kruskal重构树裸题, Sunshine互测的A题就是Kruskal重构树,我通过互测了解到了这个神奇的东西... 理解起来应该没什么难度吧,但是我的Peaks连WA,,, 省选估计要滚粗了TwT ...

  9. 【BZOJ-3545&3551】Peaks&加强版 Kruskal重构树 + 主席树 + DFS序 + 倍增

    3545: [ONTAK2010]Peaks Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 1202  Solved: 321[Submit][Sta ...

随机推荐

  1. c# winform 获取当前程序运行根目录

    1 // 获取程序的基目录. 2 System.AppDomain.CurrentDomain.BaseDirectory 3 4 5 // 获取模块的完整路径. 6 System.Diagnosti ...

  2. Repeater控件,判断最少选择一行记录

    本演示中,教会大家使用jQuery来判断Repeater控件,最少选择一行记录. 在Repeater控件中,每行第一列放置一个CheckBox,然后在Repeater控件之外,放置一个Button按钮 ...

  3. Entity Framework系列文章目录

    Entity Framework系列文章目录Entity Framework系列文章目录Entity Framework系列文章目录Entity Framework系列文章目录

  4. Android - 注解

    原理: http://www.cnblogs.com/Fndroid/p/5354644.html http://www.jianshu.com/p/28edf5352b63 开源库: ButterK ...

  5. Java - 生产者消费者问题

    Java多线程系列--“基础篇”11之 生产消费者问题 概要 本章,会对“生产/消费者问题”进行讨论.涉及到的内容包括:1. 生产/消费者模型2. 生产/消费者实现 转载请注明出处:http://ww ...

  6. HTML自定义标签与标签自定义属性

    大部分浏览器支持自定义HTML标签和为标准标签自定义属性,而且很多浏览器对这两种自定义行为的支持都很直接了当. 自定义HTML标签 在firefox.chrome这种现代浏览器里,自定义标签很简单,就 ...

  7. 使用ECharts画K线图

    需引入echarts.js插件,开发环境建议选择源代码版本,该版本包含了常见的警告和错误提示.下载地址 http://echarts.baidu.com/download.html 下面是代码,注释很 ...

  8. idea配置热部署

    第一步:添加依赖使用spring-boot-devtools提供的开发者工具spring-boot项目中引入如下依赖 <dependency><groupId>org.spri ...

  9. HTML:target=_blank、target=_top、target=_parent、target=_self 的区别

    HTML:target=_blank.target=_top.target=_parent.target=_self 的区别 _blank 在新窗口中打开链接_parent 在父窗体中打开链接_sel ...

  10. web界面 之 登录 (初稿)

    web登录一般注意以下几点: 1)拥有元素:用户名,密码(密码字符显示与隐藏功能),登录按钮,忘记密码链接(忘记用户名链接),注册链接 2)用户体验: •页面显示,光标默认停在第一个输入框 利用htm ...