[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)次操作:操作分为:在末尾插入一 ...
随机推荐
- border:none与border:0的区别
border:none与border:0的区别体现为两点:一是理论上的性能差异,二是浏览器兼容性的差异. 性能差异: [border:0;]把border设为“0”像素效果等于border-width ...
- 20.计算速度最快的valarray
#include <string> #include <iostream> //用于计算,计算的性能高于vector与array #include <valarray&g ...
- java9新特性-18-统一的JVM日志系统
1.官方Feature 158: Unified JVM Logging 271: Unified GC Logging 2.使用说明 日志是解决问题的唯一有效途径:曾经很难知道导致JVM性能问题和导 ...
- Spring深入浅出(四)AOP面向切面
面向切面编程--AOP AOP(Aspect Oriented Programming),程序员称之为面向切面编程,是Spring框架除了IOC之外的另一个核心概念. AOP是对OOP(面向对象编程) ...
- 关于ListView的一些不常用到的属性
1.setCacheColorHint自定义listview的时候,当你不使用Android:cacheColorHint=“#00000000”会出现下面选中一个空间黑色底色的情况,破坏整体美观度 ...
- 【noip2016】蚯蚓(单调性+队列)
题目贼长 大意是你有n个线段,每一秒你要拿出来最长的一个线段切成两段长度为[p*u](向下取整)和u-[p*u]两段(其中u是线段长,p是一个大于0小于1的实数)没被切的线段长度加q(0<q&l ...
- Spring配置方式
Spring配置方式 第一阶段:xml配置 在spring 1.x时代,使用spring开发满眼都是xml配置的bean,随着项目的扩大, 我们需要把xml配置文件分放到不同的配置文件中,那时 ...
- 从头认识java-18.2 主要的线程机制(5)-守护线程与非守护线程
这一章节我们来讨论一下守护线程与非守护线程. 1.什么是守护线程?什么是非守护线程? 非守护线程:Java虚拟机在它全部非守护线程已经离开后自己主动离开. 守护线程:守护线程则是用来服务用户线程的,假 ...
- 【Hibernate步步为营】--(一对多映射)之单向关联
上篇文章讨论了双向关联的一对一映射,用了两个章节,主要是从主键和外键两种关联映射展开具体讨论.双向关联的映射须要在两个映射文件里分别加入相互的相应关系.斌刚在相应的类中加入相应的关联类的属性.这样在一 ...
- Codeforces Educational Codeforces Round 8 A. Tennis Tournament
大致题意: 网球比赛,n个參赛者,每场比赛每位选手b瓶水+裁判1瓶水,所有比赛每一个參赛者p条毛巾 每一轮比赛有2^k个人參加比赛(k为2^k<=n中k的最大值),下一轮晋级人数是本轮每场比赛的 ...