链接

题解

首先很容易想到对每个点暴力跑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]飞飞侠 并查集优化最短路的更多相关文章

  1. BZOJ2143 飞飞侠 & [校内NOIP2018模拟20181026] 最强大脑

    Time Limit: 50 Sec Memory Limit: 259 MB Description 飞飞国是一个传说中的国度,国家的居民叫做飞飞侠.飞飞国是一个N×M的矩形方阵,每个格子代表一个街 ...

  2. POJ 1456 Supermarket(贪心+并查集优化)

    一开始思路弄错了,刚开始想的时候误把所有截止时间为2的不一定一定要在2的时候买,而是可以在1的时候买. 举个例子: 50 2  10 1   20 2   10 1    50+20 50 2  40 ...

  3. hdu 4641 K-string SAM的O(n^2)算法 以及 SAM+并查集优化

    链接:http://acm.hdu.edu.cn/showproblem.php?pid=4641 题意:有一个长度为n(n < 5e4)的字符串,Q(Q<=2e5)次操作:操作分为:在末 ...

  4. 洛谷 3295 [SCOI2016]萌萌哒——并查集优化连边

    题目:https://www.luogu.org/problemnew/show/P3295 当要连的边形如 “一段区间内都是 i 向 i+L 连边” 的时候,用并查集优化连边. 在连边的时候,如果要 ...

  5. POJ-1456 Supermarket(贪心,并查集优化)

    Supermarket Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 10725 Accepted: 4688 Descript ...

  6. Supermarket---poj456(贪心并查集优化)

    题目链接:http://poj.org/problem?id=1456 题意是现有n个物品,每个物品有一个保质期和一个利润,现在每天只能卖一个商品,问最大的利润是多少,商品如果过期了就不能卖了: 暴力 ...

  7. POJ 1456——Supermarket——————【贪心+并查集优化】

    Supermarket Time Limit:2000MS     Memory Limit:65536KB     64bit IO Format:%I64d & %I64u Submit  ...

  8. 近期公共祖先(LCA)——离线Tarjan算法+并查集优化

    一. 离线Tarjan算法 LCA问题(lowest common ancestors):在一个有根树T中.两个节点和 e&sig=3136f1d5fcf75709d9ac882bd8cfe0 ...

  9. hdu 4641K-string SAM的O(n^2)算法 以及 SAM+并查集优化

    转载:http://www.cnblogs.com/hxer/p/5675149.html 题意:有一个长度为n(n < 5e4)的字符串,Q(Q<=2e5)次操作:操作分为:在末尾插入一 ...

随机推荐

  1. 继承—people

    public class People { private double height;//身高 private double weight;//体重 public double getHeight( ...

  2. 【DNN发布包解释】package 包裹

    package 包裹 owner 主人 dependency 附属国 azureCompatible 天青兼容 releaseNotes  发行说明 license 许可证 CoreVersion 核 ...

  3. CMake入门之创建一个基于PCL的最小工程

    最近在学习PCL,借助Cmake可省去繁琐的添加包含目录和依赖库操作. 一个典型的CMakeLists.txt内容通常为: cmake_minimum_required(VERSION 2.6 FAT ...

  4. mutt发邮件

    在 /etc/Muttrc 文件添加以下内容:   set from="laughingliang@chaincar.com" set use_from=yes set envel ...

  5. bzoj5085: 最大 暴力 二分

    Code: #include<cstdio> #include<algorithm> #include<cstring> #include<iostream& ...

  6. TP5 模板渲染语法

    每次都要去网上找,又发现都不全.所以自己记录一下 volist:循环 {volist name="collection" id="v"} {/volist} i ...

  7. HDU-6109 数据分割 并查集(维护根节点)

    题目链接:https://cn.vjudge.net/problem/HDU-6109 题意 给出多组等式不等式 对于每一个式子,首先判断是否不可能 如果不可能,记录本组正确式子的个数,然后进入下一组 ...

  8. 今日SGU 5.28

    SGU 121 题意:给你一张图,问你每个顶点必须有黑白两条边(如果它的边数>=2),问你怎么染色,不行就输出no 收获:你会发现不行的情况只有一个单纯的奇数环的时候,反之我们交替染色即可 #i ...

  9. ArcSDE学习笔记--------增、删、改、查操作

    建立连接 package org.lq.ssm.gp.controller; import com.esri.sde.sdk.client.SeConnection; import com.esri. ...

  10. SpringMvc 系统启动时加载数据到内存中

    SpringMvc 系统启动时加载数据到内存中 学习了:http://blog.csdn.net/newstruts/article/details/18668269 https://www.cnbl ...