【BFS】【并查集】【Tarjan】【LCA】Gym - 101173H - Hangar Hurdles
给你一张地图,给你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的更多相关文章
- Gym - 101173H Hangar Hurdles (kruskal重构树/最小生成树+LCA)
题目大意:给出一个n*n的矩阵,有一些点是障碍,给出Q组询问,每组询问求两点间能通过的最大正方形宽度. 首先需要求出以每个点(i,j)为中心的最大正方形宽度mxl[i][j],可以用二维前缀和+二分或 ...
- P5836 [USACO19DEC]Milk Visits S 从并查集到LCA(最近公共祖先) Tarjan算法 (初级)
为什么以它为例,因为这个最水,LCA唯一黄题. 首先做两道并查集的练习(估计已经忘光了).简单来说并查集就是认爸爸找爸爸的算法.先根据线索理认爸爸,然后查询阶段如果发现他们的爸爸相同,那就是联通一家的 ...
- BZOJ1051:受欢迎的牛(并查集 / Tarjan)
1051: [HAOI2006]受欢迎的牛 Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 8161 Solved: 4460 Description ...
- 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 ...
- 计蒜客 444 / xtuoj 1024 京东的物流路径(并查集+离线lca)或者 (点分治)
题意:一颗树,定义一条路径的权值等于路径的边权之和,需要求这颗树所有路径中权值的最大值 思路: 考虑到路径权值与点权的最值有关,而最值的问题通常可以通过排序就行处理,于是想到先把点权排序. 容易看出如 ...
- hdu 5652 India and China Origins(二分+bfs || 并查集)BestCoder Round #77 (div.2)
题意: 给一个n*m的矩阵作为地图,0为通路,1为阻碍.只能向上下左右四个方向走.每一年会在一个通路上长出一个阻碍,求第几年最上面一行与最下面一行会被隔开. 输入: 首行一个整数t,表示共有t组数据. ...
- BZOJ 1098 [POI2007]办公楼biu(反向图bfs+并查集优化)
[题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=1098 [题目大意] 现在有一张图,要求将这张图的点划分为尽量多的分组,对于不同分组的两 ...
- BZOJ 4668: 冷战 并查集&&暴力LCA(雾)
利用并查集按秩合并,保存每个点合并的时间: 求时间时,就一直跳u=fa[u],并记录路径上时间的最大值,代表最后一次合并的时间 #include<cstdio> #include<i ...
- HDU ACM 2586 How far away ?LCA->并查集+Tarjan(离线)算法
题意:一个村子有n个房子,他们用n-1条路连接起来,每两个房子之间的距离为w.有m次询问,每次询问房子a,b之间的距离是多少. 分析:近期公共祖先问题,建一棵树,求出每一点i到树根的距离d[i],每次 ...
随机推荐
- jq_从右向右的滑入滑出效果
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...
- 线程,JSP,Servlet面试题
线程编程方面 60.java中有几种方法可以实现一个线程?用什么关键字修饰同步方法? stop()和suspend()方法为何不推荐使用? 答:有两种实现方法,分别是继承Thread类与实现Runna ...
- mysql 设置字符集
可以用:show create table table_name查看建表信息 也可用: show create database database_name查看建库信息 mysql> creat ...
- 利用Python 发送邮件
概要 我们都知道SMTP(简单邮件传输协议),是一组用于从原地址到目的地址传输邮件的规范,通过它来控制邮件的中转方式.SMTP规定电子邮件应该如何格式化.如何加密,以及如何在邮件服务器之间传递.SMT ...
- mysql cast函数
CAST函数语法规则是:Cast(字段名 as 转换的类型 ),其中类型可以为: CHAR[(N)] 字符型 DATE 日期型DATETIME 日期和时间型DECIMAL float型SIGNED i ...
- 网络设备之分配net_device结构
注册网络设备时,会调用pci_driver->probe函数,以e100为例,最终会调用alloc_netdev_mqs来分配内存,并且在分配内存后调用setup函数(以太网为ether_set ...
- Linux 入门记录:十八、Linux 系统启动流程 + 单用户修改 root 密码 + GRUB 加密
一.系统启动流程 一般来说,Linux 系统的启动流程是这样的: 1. 开机之后,位于计算机主板 ROM 芯片上的 BIOS 被最先读取,在进行硬件和内存的校验以及 CPU 的自检没有异常后, BIO ...
- 比特币编译(Ubuntu 16.04)
安装比特币需要的所有库 sudo apt-get install build-essential libtool autotools-dev automake pkg-config libssl-de ...
- 2017多校第9场 HDU 6166 Senior Pan 堆优化Dij
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6166 题意:给你一个有向图,然后给你k个点,求其中一个点到另一个点的距离的最小值. 解法:枚举二进制位 ...
- [Deep dig] ViewController初始化过程调查
代码:https://github.com/xufeng79x/ViewControllerLife 1.简介: 介绍xib方式.storyborad方式以及code方式下ViewController ...