[BZOJ2143]飞飞侠 并查集优化最短路
题解
首先很容易想到对每个点暴力跑Dijkstra,但是这样边数是 \(N^4\) 的,考虑优化
发现每次松弛的时候,都要把整个地图扫一遍,每个节点都要重复扫很多次,如果我们在一个点不会再被更新的时候,用并查集跳过去,那么就可以降低复杂度
如果将点插入堆时,比较 \(dis[i]+w[i]\) 而不是 \(dis[i]\) ,这样可以保证一个点被更新后不会再一次被更新。
现在证明上述结论,以及这样做仍然可以得到正确的最短路。
假设点 \(x\) 已经得到了最短路,证明用该点更新的 \(y\) 也得到了最短路
反证,假设存在路径 $ x’ \to y$ 使 \(dis[y]\) 更小,且在 \(x\) 更新 \(y\) 之后,那么有 \(dis[x']+w[x']< dis[x]+w[x]\) ,因为 \(x'\) 在 \(x\) 之后,有 \(dis[x']+w[x']\ge dis[x]+w[x]\),两式矛盾,运用数学归纳法,可知上述结论成立,以及起点 \(s\) 到每一点的最短路径就是 \(dis[i]\)
因此,用并查集合并已经更新过的点,再一次扫描到的时候,直接跳过即可,边数优化成 \(N^2\)
复杂度 \(O(N^2logN)\)
#include<bits/stdc++.h>
#define REP(i,a,b) for(int i(a);i<=(b);++i)
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int>pii;
inline int read(){char c,p=0;int w;
while(isspace(c=getchar()));if(c=='-')p=1,c=getchar();w=c&15;
while(isdigit(c=getchar()))w=w*10+(c&15);return p?-w:w;
}
template<typename T,typename U>inline bool smin(T&x,const U&y){return x>y?x=y,1:0;}
template<typename T,typename U>inline bool smax(T&x,const U&y){return x<y?x=y,1:0;}
const int N=155;
int n,m,a[N][N],b[N][N],d[3][N][N],vis[N][N],fa[N][N];
priority_queue< pair<int,pii> >q;
#define xx first
#define yy second
inline int find(int*f,int x){return f[x]?f[x]=find(f,f[x]):x;}
inline void solve(int d[N][N],pii s){
REP(i,1,n)REP(j,1,m)d[i][j]=1e9;
memset(vis,0,sizeof vis);
memset(fa,0,sizeof fa);
d[s.xx][s.yy]=0;
q.push(make_pair(-a[s.xx][s.yy],s));fa[s.xx][s.yy]=s.yy+1;
while(!q.empty()){
pii u=q.top().yy;q.pop();
const int&x=u.xx,&y=u.yy;
if(vis[x][y])continue;vis[x][y]=1;
int lx=max(1,x-b[x][y]),rx=min(n,x+b[x][y]);
REP(i,lx,rx){
int t=b[x][y]-abs(i-x),ly=max(1,y-t),ry=min(m,y+t);
for(int j=find(fa[i],ly);j<=ry;j=find(fa[i],j)){
if(smin(d[i][j],d[x][y]+a[x][y]))q.push(make_pair(-d[i][j]-a[i][j],pii(i,j)));
fa[i][j]=j+1;
}
}
}
}
pii s[3];
const char ss[]="XYZ";
int main(){
n=read(),m=read();
REP(i,1,n)REP(j,1,m)b[i][j]=read();
REP(i,1,n)REP(j,1,m)a[i][j]=read();
REP(i,0,2)s[i].xx=read(),s[i].yy=read(),solve(d[i],s[i]);
int dis=1e9;
int ans=-1;
REP(i,0,2){
#define d(p) d[p][s[i].xx][s[i].yy]
if(smin(dis,d(0)+d(1)+d(2)))ans=i;
}
if(~ans)printf("%c\n%d",ss[ans],dis);
else puts("NO");
return 0;
}
[BZOJ2143]飞飞侠 并查集优化最短路的更多相关文章
- BZOJ2143 飞飞侠 & [校内NOIP2018模拟20181026] 最强大脑
Time Limit: 50 Sec Memory Limit: 259 MB Description 飞飞国是一个传说中的国度,国家的居民叫做飞飞侠.飞飞国是一个N×M的矩形方阵,每个格子代表一个街 ...
- POJ 1456 Supermarket(贪心+并查集优化)
一开始思路弄错了,刚开始想的时候误把所有截止时间为2的不一定一定要在2的时候买,而是可以在1的时候买. 举个例子: 50 2 10 1 20 2 10 1 50+20 50 2 40 ...
- hdu 4641 K-string SAM的O(n^2)算法 以及 SAM+并查集优化
链接:http://acm.hdu.edu.cn/showproblem.php?pid=4641 题意:有一个长度为n(n < 5e4)的字符串,Q(Q<=2e5)次操作:操作分为:在末 ...
- 洛谷 3295 [SCOI2016]萌萌哒——并查集优化连边
题目:https://www.luogu.org/problemnew/show/P3295 当要连的边形如 “一段区间内都是 i 向 i+L 连边” 的时候,用并查集优化连边. 在连边的时候,如果要 ...
- POJ-1456 Supermarket(贪心,并查集优化)
Supermarket Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 10725 Accepted: 4688 Descript ...
- Supermarket---poj456(贪心并查集优化)
题目链接:http://poj.org/problem?id=1456 题意是现有n个物品,每个物品有一个保质期和一个利润,现在每天只能卖一个商品,问最大的利润是多少,商品如果过期了就不能卖了: 暴力 ...
- POJ 1456——Supermarket——————【贪心+并查集优化】
Supermarket Time Limit:2000MS Memory Limit:65536KB 64bit IO Format:%I64d & %I64u Submit ...
- 近期公共祖先(LCA)——离线Tarjan算法+并查集优化
一. 离线Tarjan算法 LCA问题(lowest common ancestors):在一个有根树T中.两个节点和 e&sig=3136f1d5fcf75709d9ac882bd8cfe0 ...
- hdu 4641K-string SAM的O(n^2)算法 以及 SAM+并查集优化
转载:http://www.cnblogs.com/hxer/p/5675149.html 题意:有一个长度为n(n < 5e4)的字符串,Q(Q<=2e5)次操作:操作分为:在末尾插入一 ...
随机推荐
- BackTrack5里使用OpenVAS
不多说,直接上干货! 前提 VM虚拟机的 BackTrack5安装完美图文教程: http://download.csdn.net/detail/u010106732/9845495 关于OpenAV ...
- fullpage中大的图片超过一屏怎么在手机端滑动显示?
fullpage中大的图片超过一屏怎么在手机端滑动显示?(设置overflow电脑端是会出现滚动条的,但是在手机端不出现滚动条,图片也不可左右滑动显示) var $window = $(window) ...
- 《剑指offer》包含min函数的栈
一.题目描述 定义栈的数据结构,请在该类型中实现一个能够得到栈最小元素的min函数. 二.输入描述 输入栈 三.输出描述 最小值 四.牛客网提供的框架 class Solution { public: ...
- PUBG
题目描述 最近,喜爱ACM的PBY同学沉迷吃鸡,无法自拔,于是又来到了熟悉的ERANGEL.经过一番搜寻,PBY同学准备动身前往安全区,但是,地图中埋伏了许多LYB,PBY的枪法很差,希望你能够帮他找 ...
- <<大学>>原文
大学之道,在明明德,在亲民,在止于至善.知止而后有定,定而后能静,静而后能安,安而后能虑,虑而后能得.物有本末,事有终始,知所先后,则近道矣. 古之欲明明德于天下者,先治其国,欲治其国者,先齐其家:欲 ...
- ln---创建链接
ln命令用来为文件创件连接,连接类型分为硬连接和符号连接两种,默认的连接类型是硬连接.如果要创建符号连接必须使用"-s"选项. 注意:符号链接文件不是一个独立的文件,它的许多属性依 ...
- main()函数的形参
main函数中的第一个参数argc代表的是向main函数传递的参数个数,第二个参数argv数组代表执行的程序名称和执行程序时输入的参数 #include <stdio.h> int mai ...
- 洛谷 P1056 排座椅
P1056 排座椅 题目描述 上课的时候总会有一些同学和前后左右的人交头接耳,这是令小学班主任十分头疼的一件事情.不过,班主任小雪发现了一些有趣的现象,当同学们的座次确定下来之后,只有有限的D对同学上 ...
- Objective-C - NSInteger转换NSString
NSInteger不是对象, 转换为long匹配64位系统, 再组成字符串(%ld). NSString *inStr = [NSString stringWithFormat: @"%ld ...
- PHP 保留两位小数,且不四舍五入
$value = '555.09988'; floor($value*100)/100;