BZOJ 2143

新技能:并查集优化最短路。

暴力最短路是$O(n^4)$的,然后拿个线段树优化一下连边就$O($能过$)$了。

但是这样都太慢了。

我们考虑一个点如果之前被更新过了,那么之后就不会被更新了,所以我们只要能跳过这个已经被更新过的点,直接去更新没有更新过的点就行了,刚好对应了一个并查集的路径压缩,这样子每一次跳到一个没有更新过的点就是$O(1)$的了。

每一个点拿出来的更新的时候其实是要付出它的点权,所以我们要把$dis_{x, y}  + a_{x, y}$一起丢到堆里去才能保证转移的正确性。

还是不会算时间复杂度,但是非常优秀。

Code:

#include <cstdio>
#include <cstring>
#include <queue>
using namespace std;
typedef long long ll; const int N = ;
const ll inf = 0x3f3f3f3f3f3f3f3f; int n, m, b[N][N], ufs[N][N], sx[], sy[];
ll a[N][N], dis[N][N], ans[];
bool vis[N][N]; struct Node {
int x, y;
ll d; inline Node (int nowX = , int nowY = , ll nowD = 0LL) {
x = nowX, y = nowY, d = nowD;
} friend bool operator < (const Node &u, const Node &v) {
return u.d > v.d;
} };
priority_queue <Node> Q; template <typename T>
inline void read(T &X) {
X = ; char ch = ; T op = ;
for(; ch > '' || ch < ''; ch = getchar())
if(ch == '-') op = -;
for(; ch >= '' && ch <= ''; ch = getchar())
X = (X << ) + (X << ) + ch - ;
X *= op;
} inline int max(int x, int y) {
return x > y ? x : y;
} inline int min(int x, int y) {
return x > y ? y : x;
} inline int abs(int x) {
return x > ? x : -x;
} int find(int x, int y) {
return ufs[x][y] == y ? y : ufs[x][y] = find(x, ufs[x][y]);
} void dij(int st) {
for(int i = ; i <= n; i++)
for(int j = ; j <= m + ; j++) {
dis[i][j] = inf;
ufs[i][j] = j;
vis[i][j] = ;
}
dis[sx[st]][sy[st]] = 0LL;
Q.push(Node(sx[st], sy[st], a[sx[st]][sy[st]]));
ufs[sx[st]][sy[st]] = sy[st] + ;
for(; !Q.empty(); ) {
Node out = Q.top(); Q.pop();
int x = out.x, y = out.y;
if(vis[x][y]) continue;
vis[x][y] = ; int ln = max(, x - b[x][y]), rn = min(n, x + b[x][y]);
for(int i = ln; i <= rn; i++) {
int stp = b[x][y] - abs(i - x);
int lm = max(, y - stp), rm = min(m, y + stp);
for(int j = find(i, lm); j <= rm; j = find(i, j)) {
if(dis[i][j] > dis[x][y] + a[x][y]) {
dis[i][j] = dis[x][y] + a[x][y];
Q.push(Node(i, j, dis[i][j] + a[i][j]));
}
ufs[i][j] = j + ;
}
}
}
} int main() {
freopen("4.in", "r", stdin);
// freopen("my.out", "w", stdout); read(n), read(m);
for(int i = ; i <= n; i++)
for(int j = ; j <= m; j++)
read(b[i][j]);
for(int i = ; i <= n; i++)
for(int j = ; j <= m; j++)
read(a[i][j]); for(int i = ; i <= ; i++)
read(sx[i]), read(sy[i]); for(int i = ; i <= ; i++) {
dij(i);
for(int j = ; j <= ; j++) ans[j] += dis[sx[j]][sy[j]];
} ll res = inf, pos = ;
for(int i = ; i <= ; i++)
if(ans[i] < res) res = ans[i], pos = i; if(res >= inf) {
puts("NO");
return ;
} if(pos == ) puts("X");
if(pos == ) puts("Y");
if(pos == ) puts("Z"); printf("%lld\n", res);
return ;
}

Luogu 4473 [国家集训队]飞飞侠的更多相关文章

  1. luogu4473 BZOJ2143 2011[国家集训队]飞飞侠

    题目戳这里 有问题可以在博客@ 应该还会有人来看吧,嘻嘻 正题: 题目大意: 题目很清楚,就是一个点有一定的范围,会有一定的花费 求三个点中的任意两个点到另一个点的最小花费 (麻麻教育我千万读好题目( ...

  2. luogu P2757 [国家集训队]等差子序列

    题目链接 luogu P2757 [国家集训队]等差子序列 题解 线段树好题 我选择暴力 代码 // luogu-judger-enable-o2 #include<cstdio> inl ...

  3. luogu P2619 [国家集训队2]Tree I

    题目链接 luogu P2619 [国家集训队2]Tree I 题解 普通思路就不说了二分增量,生成树check 说一下坑点 二分时,若黑白边权有相同,因为权值相同优先选白边,若在最有增量时出现黑白等 ...

  4. [Luogu P1829] [国家集训队]Crash的数字表格 / JZPTAB (莫比乌斯反演)

    题面 传送门:洛咕 Solution 调到自闭,我好菜啊 为了方便讨论,以下式子\(m>=n\) 为了方便书写,以下式子中的除号均为向下取整 我们来颓柿子吧qwq 显然,题目让我们求: \(\l ...

  5. Luogu P1297 [国家集训队]单选错位

    P1297 [国家集训队]单选错位 题目背景 原 <网线切割>请前往P1577 题目描述 gx和lc去参加noip初赛,其中有一种题型叫单项选择题,顾名思义,只有一个选项是正确答案.试卷上 ...

  6. Luogu P2619 [国家集训队2]Tree I(WQS二分+最小生成树)

    P2619 [国家集训队2]Tree I 题意 题目描述 给你一个无向带权连通图,每条边是黑色或白色.让你求一棵最小权的恰好有\(need\)条白色边的生成树. 题目保证有解. 输入输出格式 输入格式 ...

  7. 【luogu P1494 [国家集训队]小Z的袜子】 题解

    题目链接:https://www.luogu.org/problemnew/show/P1494 #include <cstdio> #include <algorithm> ...

  8. 【luogu P1903 [国家集训队]数颜色】 题解

    题目链接:https://www.luogu.org/problemnew/show/P1903 裸的...带修莫队... 比较麻烦吧(对我来说是的) 两个变量分开记录查询和修改操作. #includ ...

  9. BZOJ 2127 / Luogu P1646 [国家集训队]happiness (最小割)

    题面 BZOJ传送门 Luogu传送门 分析 这道题又出现了二元关系,于是我们只需要解方程确定怎么连边就行了 假设跟SSS分在一块是选文科,跟TTT分在一块是选理科,先加上所有的收益,再来考虑如何让需 ...

随机推荐

  1. Mac各个文件夹表示的意思

    ca参考链接:http://www.jb51.net/os/MAC/130901.html

  2. gatsbyjs 使用

    1. 安装 npm install --global gatsby-cli 2. 使用 // 创建项目 gatsby new dalong cd dalong // 启动 gatsby develop ...

  3. C#网络编程(同步传输字符串) - Part.2

    服务端客户端通信 在与服务端的连接建立以后,我们就可以通过此连接来发送和接收数据.端口与端口之间以流(Stream)的形式传输数据,因为几乎任何对象都可以保存到流中,所以实际上可以在客户端与服务端之间 ...

  4. 11g R2 rac linstener 监听配置

    两个节点host,ipvip ,scan的信息 #eth0-Public IP 162.12.0.1    cqltjcpt1 162.12.0.3    cqltjcpt2 #eth1 PRIVAT ...

  5. hive字段原理--有删除一列想到的

    hive删除一张表的字段不会动数据文件,只是修改了一下metadata表里面的表定义:所以会出现一种情况:就是这张表如果之前数据是满的(个格列都有数据),那么被删除的那列后数据都往前窜了一个,最后一个 ...

  6. python学习之logging

    学习地址:http://blog.csdn.net/zyz511919766/article/details/25136485 首先如果我们想简要的打印出日志,可以: import logging l ...

  7. sql for 存储过程格式

    sql DELIMITER && CREATE PROCEDURE test2() BEGIN DECLARE i INT; ; DO ')); ; END WHILE; END; & ...

  8. php sprintf()

    在写php代码的时候,有时候会用到sprintf()这个函数,那么它是怎么用的呢? 学习源头: http://www.w3school.com.cn/php/func_string_sprintf.a ...

  9. jetty中war包解压路径

    这是个很奇怪的问题,如果下载好了jetty直接放入war包运行,项目会被解压到C盘的临时文件夹中.但是如果你在${JETTY_HOME}文件夹,也就是jetty解压后的根目录中新建,注意是新建一个wo ...

  10. (转)c#实现开机自启动

    RegistryKey key = Registry.LocalMachine.OpenSubKey("SOFTWARE\\Microsoft\\Windows\\CurrentVersio ...