bzoj 4242 水壶 (多源最短路+最小生成树+启发式合并)
4242: 水壶
Time Limit: 50 Sec Memory Limit: 512 MB
Submit: 1028 Solved: 261
[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
跟bzoj4144题一样。。不过由于每条边距离相等,所以我们要把优先队列换成普通队列来减少时间。我实在是口算不出来这个时间是多少,然后一开始优先队列一直过不了。看了人家ac代码是普通队列一改就过了。。。orz。不过时间也是挺极限的46s。反正过啦!
#include<bits/stdc++.h>
#define clr(x) memset(x,0,sizeof(x))
#define clr_1(x) memset(x,-1,sizeof(x))
#define INF 0x3f3f3f3f
#define LL long long
#define pb push_back
#define mod 1000000007
#define ls(i) (i<<1)
#define rs(i) (i<<1|1)
#define mp make_pair
#define fi first
#define se second
using namespace std;
const int N=2e3+;
const int M=2e5+;
typedef pair<int,int> pii;
typedef pair<LL,pii> plii;
queue<pii> que;
int mart[N][N];
char s[N];
LL dis[N][N];
int pre[N][N];
bool vis[N][N];
struct edge
{
int u,v;
LL w;
edge(int _u,int _v,LL _w):u(_u),v(_v),w(_w) {}
};
vector<edge> e;
int dirx[]={,,,-},diry[]={,-,,};
void dij(int n,int m)
{
while(!que.empty())
{
pii p=que.front();
que.pop();
int x=p.fi;
int y=p.se;
LL d=dis[x][y];
if(vis[x][y]) continue;
vis[x][y]=;
for(int i=;i<;i++)
{
int a=x+dirx[i];
int b=y+diry[i];
if(mart[a][b]) continue;
if(!pre[a][b] || dis[a][b]>d+)
{
dis[a][b]=d+;
pre[a][b]=pre[x][y];
que.push(mp(a,b));
}
else if(pre[a][b]!=pre[x][y])
e.pb(edge(pre[a][b],pre[x][y],dis[x][y]+dis[a][b]));
}
}
}
int fa[M],rfa[M];
int rk[M],dep[M];
LL up[M];
bool cmp(edge a,edge b) {return a.w<b.w;}
int Find(int u) { return fa[u]==u?u:fa[u]=Find(fa[u]);}
void Union(int n)
{
sort(e.begin(),e.end(),cmp);
for(int i=;i<=n;i++)
fa[i]=i,rk[i]=;
int sz=e.size();
for(int i=;i<sz;i++)
{
int x=e[i].u;
int y=e[i].v;
LL w=e[i].w;
x=Find(x),y=Find(y);
if(x==y) continue;
if(rk[x]<rk[y]) swap(x,y);
if(rk[x]==rk[y]) rk[x]++;
fa[y]=x,rfa[y]=x,up[y]=w;
}
return ;
}
void dealdep(int u)
{
if(Find(u)==u)
{
dep[u]=;
return ;
}
dealdep(rfa[u]);
dep[u]=dep[rfa[u]]+;
return ;
}
LL solve(int u,int v)
{
LL maxn=;
if(Find(u)!=Find(v)) return -;
if(dep[u]<dep[v]) swap(u,v);
while(dep[u]>dep[v])
{
maxn=max(maxn,up[u]);
u=rfa[u];
}
while(u!=v)
{
maxn=max(maxn,up[u]);
maxn=max(maxn,up[v]);
u=rfa[u],v=rfa[v];
}
return maxn;
}
int main()
{
int n,m,k,q;
scanf("%d%d%d%d",&n,&m,&k,&q);
for(int i=;i<=n;i++)
{
scanf("%s",s+);
for(int j=;j<=m;j++)
if(s[j]=='.') mart[i][j]=;
else mart[i][j]=;
}
for(int i=;i<=m+;i++)
mart[][i]=mart[n+][i]=;
for(int i=;i<=n+;i++)
mart[i][]=mart[i][m+]=;
clr_1(dis);
for(int i=;i<=k;i++)
{
int u,v;
scanf("%d%d",&u,&v);
dis[u][v]=;
pre[u][v]=i;
que.push(mp(u,v));
}
dij(n,m);
Union(k);
for(int i=;i<=k;i++)
if(!dep[i]) dealdep(i);
// for(int i=1;i<=k;i++)
// cout<<"pos:"<<pt[i]/m+1<<" "<<pt[i]%m+1<<" blk:"<<Find(pt[i])/m+1<<" "<<Find(pt[i])%m+1<<" fa:"<<rfa[pt[i]]/m+1<<" "<<rfa[pt[i]]%m+1<<" dep:"<<dep[pt[i]]<<" val:"<<up[pt[i]]<<endl;
while(q--)
{
int u,v;
scanf("%d%d",&u,&v);
printf("%lld\n",solve(u,v));
}
return ;
}
bzoj 4242 水壶 (多源最短路+最小生成树+启发式合并)的更多相关文章
- 4144: [AMPPZ2014]Petrol (多源最短路+最小生成树+启发式合并)
4144: [AMPPZ2014]Petrol Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 752 Solved: 298[Submit][Sta ...
- BZOJ 4242: 水壶 Kruskal+BFS
4242: 水壶 Time Limit: 40 Sec Memory Limit: 256 MBSubmit: 427 Solved: 112[Submit][Status][Discuss] D ...
- BZOJ 4242 水壶(BFS建图+最小生成树+树上倍增)
题意 JOI君所居住的IOI市以一年四季都十分炎热著称. IOI市是一个被分成纵H*横W块区域的长方形,每个区域都是建筑物.原野.墙壁之一.建筑物的区域有P个,编号为1...P. JOI君只能进入建筑 ...
- BZOJ 4242: 水壶(Kruskal重构树 + Bfs)
题意 一块 \(h ∗ w\) 的区域,存在障碍.空地.\(n\) 个建筑,从一个建筑到另一个建筑的花费为:路径上最长的连续空地的长度. \(q\) 次询问:从建筑 \(s_i\) 到 \(t_i\) ...
- BZOJ 1483:[HNOI2009]梦幻布丁(链表+启发式合并)
[HNOI2009]梦幻布丁 Description N个布丁摆成一行,进行M次操作.每次将某个颜色的布丁全部变成另一种颜色的,然后再询问当前一共有多少段颜色.例如颜色分别为1,2,2,1的四个布丁一 ...
- BZOJ 1483:[HNOI2009]梦幻布丁(链表启发式合并)
http://www.lydsy.com/JudgeOnline/problem.php?id=1483 题意:中文. 思路:对于每一种颜色,用一个链表串起来,一开始保存一个答案,后面颜色替换的时候再 ...
- Bzoj 2733: [HNOI2012]永无乡 数组Splay+启发式合并
2733: [HNOI2012]永无乡 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 3955 Solved: 2112[Submit][Statu ...
- Bzoj 2733: [HNOI2012]永无乡(线段树+启发式合并)
2733: [HNOI2012]永无乡 Time Limit: 10 Sec Memory Limit: 128 MB Description 永无乡包含 n 座岛,编号从 1 到 n,每座岛都有自己 ...
- 【BZOJ4144】[AMPPZ2014]Petrol(最短路+最小生成树+并查集)
Description 给定一个n个点.m条边的带权无向图,其中有s个点是加油站. 每辆车都有一个油量上限b,即每次行走距离不能超过b,但在加油站可以补满. q次询问,每次给出x,y,b,表示出发点是 ...
随机推荐
- 文件操作fstream
c++文件操作详解 2009-04-16 20:46:35| 分类: C/C++|举报|字号 订阅 C++ 通过以下几个类支持文件的输入输出: ofstream: 写操作(输出)的文件类 (由ost ...
- zTree静态树与动态树的用法——(七)
0.[简介] zTree 是利用 JQuery 的核心代码,实现一套能完成大部分常用功能的 Tree 插件 兼容 IE.FireFox.Chrome 等浏览器 在一个页面内可同时生成多个 Tree 实 ...
- Spring4笔记3--Bean的装配
Bean的装配: Bean 的装配,即 Bean 对象的创建.容器根据代码要求创建 Bean 对象后再传递给代码的过程,称为 Bean 的装配. 1. 创建Bean对象的方式: 1. 通过 getBe ...
- Strusts2笔记5--数据验证
数据验证: 输入验证分为客户端验证与服务器端验证.客户端验证主要通过JavaScript脚本进行,而服务器端验证主要是通过Java代码进行验证. 分为以下四种情况: (1)手工编写代码,对Action ...
- MySQL 执行SQL脚本 报ERROR 1231 (42000)的解决办法【转】
今天在source mysqldump 备份文件时,发现导入的过程中报如下的错误: ERROR 1231 (42000): Variable 'time_zone' can't be set to t ...
- java 判断上传文件大小
/** * 判断文件大小 * * @param file * 文件 * @param size * 限制大小 * @param unit * 限制单位(B,K,M,G) * @return */ pu ...
- Github授权新的设备ssh接入
为Mac生成公钥 步骤: 检查本机是否已有公钥 ls -la ~/.ssh 将原来的公钥删除 rm -rf ~/.ssh 生成新的公钥(填自己的邮箱),然后除了密码,一路默认 ssh-keygen - ...
- 教你用DrawLayout 实现Android 侧滑菜单
现在的APP越来越注重用户体验,百度视频客户端有一个特效还是挺吸引人的,在主界面手指向右滑动,就可以将菜单展示出来,而主界面会被隐藏大部分,但是仍有左侧的一小部分同菜单一起展示.类似的还有天天动听,人 ...
- 将python脚本转换成exe文件--pyinstaller
遇到的大坑: 直接运行python文件效果: 执行 pyinstaller -F -w -p -i ./123.ico ./main.py 在dict文件夹下生成exe文 ...
- php 中更简洁的三元运算符 ?:
PHP 三元运算符是对参数赋值时候的一个简洁的主要用法. 一个主要的用法: PHP 三元运算符能够让你在一行代码中描述判定代码, 从而替换掉类似以下的代码: <?php if (isset($v ...