给你一张地图,给你q次询问,每次问你从A点到B点,最大能移动多大的箱子。

把每个点所能容纳的最大箱子求出来(BFS,八连通,一开始将所有边界点和障碍点入队)。然后从大到小排序。然后用并查集将相邻(四联通)的点依次链接起来,如果不路径压缩的话,那么两个节点的LCA的所能容纳的箱子大小就是答案。于是用并查集辅助建树,之后离线询问,然后Tarjan跑个LCA即可。

O(n^2+qlog(n)),log是因为map记录答案。

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<queue>
#include<vector>
#include<map>
using namespace std;
vector<int>ask[1010*1010];
int dx[]={0,1,0,-1,1,1,-1,-1},dy[]={1,0,-1,0,1,-1,1,-1};
int e,v[1010*1010],first[1010*1010],next[1010*1010];
void AddEdge(int U,int V){
v[++e]=V;
next[e]=first[U];
first[U]=e;
}
struct Point{
int x,y;
Point(const int &x,const int &y){
this->x=x;
this->y=y;
}
Point(){}
};
bool operator < (const Point &a,const Point &b){
return a.x!=b.x ? a.x<b.x : a.y<b.y;
}
map<Point,int>anss;
struct Node{
Point p;
int d;
Node(const Point &p,const int &d){
this->p=p;
this->d=d;
}
};
int n,siz[1010][1010],Siz[1010*1010],m,K;
int id[1010][1010];
bool cmp(const Point &a,const Point &b){
return siz[a.x][a.y]>siz[b.x][b.y];
}
char a[1010][1010];
queue<Node>q;
bool vis[1010][1010];
Point ps[1010*1010];
int fa[1010*1010];
int find(int x){
return x==fa[x] ? x : fa[x]=find(fa[x]);
}
Point qa[300010],qb[300010];
bool not_rt[1010*1010];
int ans[1010*1010];
bool VIS[1010*1010];
void LCA(int u)
{
ans[u]=u;
for(int i=first[u];i;i=next[i])
{
LCA(v[i]);
int f1=find(u),f2=find(v[i]);
fa[f1]=f2;
ans[find(u)]=u;
}
VIS[u]=true;
for(int i=0;i<ask[u].size();i++)
if(VIS[ask[u][i]]){
// printf("%d %d %d %d\n",min(u,ask[u][i]),max(u,ask[u][i]),ans[find(ask[u][i])],Siz[ans[find(ask[u][i])]]);
anss[Point(min(u,ask[u][i]),max(u,ask[u][i]))]=Siz[ans[find(ask[u][i])]];
}
}
bool sb_q[300010];
int main(){
// freopen("h.in","r",stdin);
scanf("%d",&n);
for(int i=1;i<=n;++i){
scanf("%s",a[i]+1);
}
for(int i=0;i<=n+1;++i){
q.push(Node(Point(i,0),0));
vis[i][0]=1;
q.push(Node(Point(i,n+1),0));
vis[i][n+1]=1;
}
for(int i=0;i<=n+1;++i){
q.push(Node(Point(0,i),0));
vis[0][i]=1;
q.push(Node(Point(n+1,i),0));
vis[n+1][i]=1;
}
for(int i=1;i<=n;++i){
for(int j=1;j<=n;++j){
if(a[i][j]=='#'){
q.push(Node(Point(i,j),0));
vis[i][j]=1;
}
}
}
for(int i=1;i<=n;++i){
for(int j=1;j<=n;++j){
id[i][j]=++m;
}
}
m=0;
while(!q.empty()){
Node U=q.front(); q.pop();
int x=U.p.x,y=U.p.y;
for(int i=0;i<8;++i){
int tx=x+dx[i],ty=y+dy[i];
if(tx>=1 && tx<=n && ty>=1 && ty<=n && !vis[tx][ty]){
q.push(Node(Point(tx,ty),U.d+1));
siz[tx][ty]=Siz[id[tx][ty]]=2*U.d+1;
vis[tx][ty]=1;
}
}
}
// for(int i=1;i<=n;++i){
// for(int j=1;j<=n;++j){
// printf("%d ",siz[i][j]);
// }
// puts("");
// }
for(int i=1;i<=n;++i){
for(int j=1;j<=n;++j){
if(siz[i][j]){
ps[++m]=Point(i,j);
}
}
}
for(int i=1;i<=m;++i){
fa[id[ps[i].x][ps[i].y]]=id[ps[i].x][ps[i].y];
}
sort(ps+1,ps+m+1,cmp);
memset(vis,0,sizeof(vis));
for(int i=1;i<=m;++i){
int x=ps[i].x,y=ps[i].y;
for(int j=0;j<4;++j){
int tx=x+dx[j],ty=y+dy[j];
if(a[tx][ty]=='.' && vis[tx][ty]){
int rt=find(id[tx][ty]);
if(rt!=find(id[x][y])){
AddEdge(id[x][y],rt);
// printf("%d %d\n",id[x][y],rt);
not_rt[rt]=1;
fa[rt]=id[x][y];
}
}
}
vis[x][y]=1;
}
scanf("%d",&K);
for(int i=1;i<=K;++i){
scanf("%d%d%d%d",&qa[i].x,&qa[i].y,&qb[i].x,&qb[i].y);
int f1=find(id[qa[i].x][qa[i].y]),f2=find(id[qb[i].x][qb[i].y]);
if(f1==f2){
ask[id[qa[i].x][qa[i].y]].push_back(id[qb[i].x][qb[i].y]);
ask[id[qb[i].x][qb[i].y]].push_back(id[qa[i].x][qa[i].y]);
}
else{
sb_q[i]=1;
}
}
for(int i=1;i<=m;++i){
fa[id[ps[i].x][ps[i].y]]=id[ps[i].x][ps[i].y];
}
for(int i=1;i<=m;++i){
if(!not_rt[id[ps[i].x][ps[i].y]]){
LCA(id[ps[i].x][ps[i].y]);
}
}
for(int i=1;i<=K;++i){
if(sb_q[i]){
puts("0");
}
else{
printf("%d\n",anss[Point(min(id[qa[i].x][qa[i].y],id[qb[i].x][qb[i].y]),
max(id[qa[i].x][qa[i].y],id[qb[i].x][qb[i].y]))]);
}
}
return 0;
}

【BFS】【并查集】【Tarjan】【LCA】Gym - 101173H - Hangar Hurdles的更多相关文章

  1. Gym - 101173H Hangar Hurdles (kruskal重构树/最小生成树+LCA)

    题目大意:给出一个n*n的矩阵,有一些点是障碍,给出Q组询问,每组询问求两点间能通过的最大正方形宽度. 首先需要求出以每个点(i,j)为中心的最大正方形宽度mxl[i][j],可以用二维前缀和+二分或 ...

  2. P5836 [USACO19DEC]Milk Visits S 从并查集到LCA(最近公共祖先) Tarjan算法 (初级)

    为什么以它为例,因为这个最水,LCA唯一黄题. 首先做两道并查集的练习(估计已经忘光了).简单来说并查集就是认爸爸找爸爸的算法.先根据线索理认爸爸,然后查询阶段如果发现他们的爸爸相同,那就是联通一家的 ...

  3. BZOJ1051:受欢迎的牛(并查集 / Tarjan)

    1051: [HAOI2006]受欢迎的牛 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 8161  Solved: 4460 Description ...

  4. Educational Codeforces Round 1 D. Igor In the Museum bfs 并查集

    D. Igor In the Museum Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/contest/598 ...

  5. 计蒜客 444 / xtuoj 1024 京东的物流路径(并查集+离线lca)或者 (点分治)

    题意:一颗树,定义一条路径的权值等于路径的边权之和,需要求这颗树所有路径中权值的最大值 思路: 考虑到路径权值与点权的最值有关,而最值的问题通常可以通过排序就行处理,于是想到先把点权排序. 容易看出如 ...

  6. hdu 5652 India and China Origins(二分+bfs || 并查集)BestCoder Round #77 (div.2)

    题意: 给一个n*m的矩阵作为地图,0为通路,1为阻碍.只能向上下左右四个方向走.每一年会在一个通路上长出一个阻碍,求第几年最上面一行与最下面一行会被隔开. 输入: 首行一个整数t,表示共有t组数据. ...

  7. BZOJ 1098 [POI2007]办公楼biu(反向图bfs+并查集优化)

    [题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=1098 [题目大意] 现在有一张图,要求将这张图的点划分为尽量多的分组,对于不同分组的两 ...

  8. BZOJ 4668: 冷战 并查集&&暴力LCA(雾)

    利用并查集按秩合并,保存每个点合并的时间: 求时间时,就一直跳u=fa[u],并记录路径上时间的最大值,代表最后一次合并的时间 #include<cstdio> #include<i ...

  9. HDU ACM 2586 How far away ?LCA-&gt;并查集+Tarjan(离线)算法

    题意:一个村子有n个房子,他们用n-1条路连接起来,每两个房子之间的距离为w.有m次询问,每次询问房子a,b之间的距离是多少. 分析:近期公共祖先问题,建一棵树,求出每一点i到树根的距离d[i],每次 ...

随机推荐

  1. Part2-HttpClient官方教程-Chapter3-HTTP状态管理

    ps:近日忙于课设与一个赛事的准备....时间真紧啊~~ 最初,HTTP被设计为一种无状态的,面向请求/响应的协议,它并没有为跨越多个逻辑相关的请求/响应交换的有状态会话做出特殊规定.随着HTTP协议 ...

  2. 浅谈linux的死锁检测 【转】

    转自:http://www.blog.chinaunix.net/uid-25942458-id-3823545.html 死锁:就是多个进程(≥2)因为争夺资源而相互等待的一种现象,若无外力推动,将 ...

  3. iOS一个项目开始创建, 部署到git服务器

    在做iOS开发时, 最开始可能你的经理部署项目, 所以你不会插手, 只是直接从git上clone下来然后就开始撸码, 如果有一天你做经理了, 你怎么去部署一个项目呢, 下面我来过一遍流程 1. 首先需 ...

  4. C基础 一个可以改变linux的函数getch

    引言  -  getch简述 引用老的TC版本getch说明. (文章介绍点有点窄,  应用点都是一些恐龙游戏时代的开发细节) #include <conio.h> /* * 立即从客户端 ...

  5. Jquery和JS实现浏览器全屏

    var fullscreen=function(){ elem=document.body; if(elem.webkitRequestFullScreen){ elem.webkitRequestF ...

  6. CSS3 icon font

    大家都知道现在各个浏览器都支持CSS3的自定义字体(@font-face),包括IE6都支持,只是各自对字体文件格式的支持不太一样.那么对于网站中用到的各种icon,我们就可以尝试使用font来实现, ...

  7. Leetcode 之Longest Valid Parentheses(39)

    有一定的难度.用堆栈记录下所有左符的位置,用变量记录下孤立右符的位置. int longestValidParentheses(const string& s) { stack<int& ...

  8. leetcode 之Copy List with Random Pointer(23)

    深拷贝一个链表,不同的是这个链表有个额外的随机指针.参考:http://blog.csdn.net/ljiabin/article/details/39054999 做法非常的巧妙,分成三步,一是新建 ...

  9. Fel表达式使用过程中需要注意的问题

    精度问题: 我们知道java中直接使用float和double参与的计算都可能会产生精度问题,比如0.1+0.3.1.0-0.9 等.所以一般财务系统,都会使用BigDecimal进行加减乘除. 在调 ...

  10. Windows + IDEA 手动开发MapReduce程序

    参见马士兵老师的博文:map_reduce 环境配置 Windows本地解压Hadoop压缩包,然后像配置JDK环境变量一样在系统环境变量里配置HADOOP_HOME和path环境变量.注意:hado ...