4144: [AMPPZ2014]Petrol

Time Limit: 10 Sec  Memory Limit: 256 MB
Submit: 457  Solved: 170
[Submit][Status][Discuss]

Description

给定一个n个点、m条边的带权无向图,其中有s个点是加油站。
每辆车都有一个油量上限b,即每次行走距离不能超过b,但在加油站可以补满。
q次询问,每次给出x,y,b,表示出发点是x,终点是y,油量上限为b,且保证x点和y点都是加油站,请回答能否从x走到y。
 

Input

第一行包含三个正整数n,s,m(2<=s<=n<=200000,1<=m<=200000),表示点数、加油站数和边数。
第二行包含s个互不相同的正整数c[1],c[2],...c[s](1<=c[i]<=n),表示每个加油站。
接下来m行,每行三个正整数u[i],v[i],d[i](1<=u[i],v[i]<=n,u[i]!=v[i],1<=d[i]<=10000),表示u[i]和v[i]之间有一条长度为d[i]的双向边。
接下来一行包含一个正整数q(1<=q<=200000),表示询问数。
接下来q行,每行包含三个正整数x[i],y[i],b[i](1<=x[i],y[i]<=n,x[i]!=y[i],1<=b[i]<=2*10^9),表示一个询问。
 

Output

输出q行。第i行输出第i个询问的答案,如果可行,则输出TAK,否则输出NIE。
 

Sample Input

6 4 5
1 5 2 6
1 3 1
2 3 2
3 4 3
4 5 5
6 4 5
4
1 2 4
2 6 9
1 5 9
6 5 8

Sample Output

TAK
TAK
TAK
NIE

HINT

 

Source

[Submit][Status][Discuss]

分析

为了回答每个询问,我们需要加油站之间的最小生成树。

求最小生成树的方式是:让所有的加油站dis为0,做多源最短路,同时记录距离每个点最近的加油站。然后枚举边,可以得到两个加油站之间的可能最短距离。做Kruskal或Prim即可。

求到最小生成树之后,用倍增法维护路径上的最大权值即可。

代码

 #include <cmath>
#include <queue>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm> using namespace std; #define N 500005
#define inf 0x3f3f3f3f int n, m, s, c[N]; struct edge
{
int x, y, w; edge(void) {};
edge(int _x, int _y, int _w) :
x(_x), y(_y), w(_w) {}; friend bool operator < (const edge &a, const edge &b)
{
return a.w < b.w;
}
}; struct step
{
int id, dis; step(void) {};
step(int a, int b) :
id(a), dis(b) {}; friend bool operator < (const step &a, const step &b)
{
return a.dis > b.dis;
}
}; namespace kirito
{
edge e[N]; int edge_cnt = ; int hd[N], to[N], vl[N], nt[N], tot; void addEdge(int x, int y, int w)
{
nt[tot] = hd[x]; to[tot] = y; vl[tot] = w; hd[x] = tot++;
nt[tot] = hd[y]; to[tot] = x; vl[tot] = w; hd[y] = tot++;
} int dis[N], from[N]; priority_queue<step> pq;
} namespace masiro
{
edge e[N]; int edge_cnt = ; void pushEdge(int x, int y, int w)
{
e[++edge_cnt] = edge(x, y, w);
} int hd[N], to[N], vl[N], nt[N], tot; void addEdge(int x, int y, int w)
{
nt[tot] = hd[x]; to[tot] = y; vl[tot] = w; hd[x] = tot++;
nt[tot] = hd[y]; to[tot] = x; vl[tot] = w; hd[y] = tot++;
} int fa[N]; int find(int u)
{
return fa[u] == u ? u : fa[u] = find(fa[u]);
} int root; int dep[N], fat[N][], mex[N][]; void predfs(int u, int f)
{
for (int i = ; i < ; ++i)
{
fat[u][i] = fat[fat[u][i - ]][i - ];
mex[u][i] = max(mex[u][i - ], mex[fat[u][i - ]][i - ]);
} for (int i = hd[u]; ~i; i = nt[i])
if (to[i] != f)
{
dep[to[i]] = dep[u] + ;
mex[to[i]][] = vl[i];
fat[to[i]][] = u;
predfs(to[i], u);
}
}
} void prework1(void)
{
using namespace kirito; memset(dis, inf, sizeof(dis)); for (int i = ; i <= s; ++i)
{
dis[c[i]] = ;
from[c[i]] = c[i];
pq.push(step(c[i], ));
} while (!pq.empty())
{
step top = pq.top(); pq.pop(); if (dis[top.id] != top.dis)
continue; for (int i = hd[top.id]; ~i; i = nt[i])
if (dis[to[i]] > vl[i] + top.dis)
{
from[to[i]] = from[top.id];
dis[to[i]] = vl[i] + top.dis;
pq.push(step(to[i], dis[to[i]]));
}
} for (int i = ; i <= m; ++i)
if (from[e[i].x] ^ from[e[i].y])
masiro::pushEdge(from[e[i].x], from[e[i].y], dis[e[i].x] + dis[e[i].y] + e[i].w);
} void prework2(void)
{
using namespace masiro; sort(e + , e + + edge_cnt); for (int i = ; i <= n; ++i)
fa[i] = i; for (int i = ; i <= edge_cnt; ++i)
{
int fx = find(e[i].x);
int fy = find(e[i].y); if (fx ^ fy)
{
fa[fx] = fy;
addEdge(e[i].x, e[i].y, e[i].w);
}
} root = n + ; for (int i = ; i <= s; ++i)
if (find(c[i]) == c[i])
addEdge(root, c[i], inf); dep[root] = ;
fat[root][] = root;
memset(mex, , sizeof(mex)); predfs(root, -);
} int lca(int x, int y)
{
using namespace masiro; int res = ; if (dep[x] < dep[y])
swap(x, y); for (int i = ; i >= ; --i)
if (dep[fat[x][i]] >= dep[y])
{
res = max(res, mex[x][i]);
x = fat[x][i];
} if (x == y)
return res; for (int i = ; i >= ; --i)
if (fat[x][i] != fat[y][i])
{
res = max(res, mex[x][i]);
res = max(res, mex[y][i]);
x = fat[x][i];
y = fat[y][i];
} res = max(res, mex[x][]);
res = max(res, mex[y][]); return res;
} signed main(void)
{
scanf("%d%d%d", &n, &s, &m); for (int i = ; i <= s; ++i)
scanf("%d", c + i); memset(kirito::hd, -, sizeof(kirito::hd));
memset(masiro::hd, -, sizeof(masiro::hd)); for (int i = ; i <= m; ++i)
{
int x, y, w; scanf("%d%d%d", &x, &y, &w); kirito::addEdge(x, y, w);
kirito::e[i] = edge(x, y, w);
} prework1();
prework2(); int q; scanf("%d", &q); for (int i = ; i <= q; ++i)
{
int x, y, w; scanf("%d%d%d", &x, &y, &w); int maxCost = lca(x, y); if (w >= maxCost)
puts("TAK");
else
puts("NIE");
}
}

BZOJ_4144.cpp

@Author: YouSiki

BZOJ 4144: [AMPPZ2014]Petrol的更多相关文章

  1. BZOJ.4144.[AMPPZ2014]Petrol(Kruskal重构树)

    BZOJ 看别人代码的时候发现哪一步都很眼熟,突然想起来,就在四个月前我好像看过还给别人讲过?mmp=v= 果然不写写就是容易忘.写了好歹忘了的时候还能复习呢(虽然和看别人的好像也没多少差别?). 首 ...

  2. 4144: [AMPPZ2014]Petrol (多源最短路+最小生成树+启发式合并)

    4144: [AMPPZ2014]Petrol Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 752  Solved: 298[Submit][Sta ...

  3. 【BZOJ】4144: [AMPPZ2014]Petrol

    题意 给定一个\(n\)个点.\(m\)条边的带权无向图,其中有\(s\)个点是加油站.每辆车都有一个油量上限\(b\),即每次行走距离不能超过\(b\),但在加油站可以补满.\(q\)次询问,每次给 ...

  4. [BZOJ 4144] Petrol

    Link: BZOJ 4144 传送门 Solution: 一道不错的图论综合题 因为只询问关键点,因此重点是要求出关键点之间的最短路,以最短路建图 记$nst[i]$为离$i$最近的关键点:可以发现 ...

  5. 【BZOJ4144】[AMPPZ2014]Petrol 最短路+离线+最小生成树

    [BZOJ4144][AMPPZ2014]Petrol Description 给定一个n个点.m条边的带权无向图,其中有s个点是加油站. 每辆车都有一个油量上限b,即每次行走距离不能超过b,但在加油 ...

  6. bzoj 4152[AMPPZ2014]The Captain

    bzoj 4152[AMPPZ2014]The Captain 给定平面上的n个点,定义(x1,y1)到(x2,y2)的费用为min(|x1-x2|,|y1-y2|),求从1号点走到n号点的最小费用. ...

  7. 循环队列+堆优化dijkstra最短路 BZOJ 4152: [AMPPZ2014]The Captain

    循环队列基础知识 1.循环队列需要几个参数来确定 循环队列需要2个参数,front和rear 2.循环队列各个参数的含义 (1)队列初始化时,front和rear值都为零: (2)当队列不为空时,fr ...

  8. BZOJ 4152: [AMPPZ2014]The Captain( 最短路 )

    先按x排序, 然后只有相邻节点的边才有用, 我们连起来, 再按y排序做相同操作...然后就dijkstra ---------------------------------------------- ...

  9. BZOJ 4143: [AMPPZ2014]The Lawyer( sort )

    水题... 排序搞出每天的会议有哪些, 然后再按照会议的开始时间和结束时间排序, 最晚开始的和最早结束的会议不是同一场而且最晚开始的时间>最早结束的会议就有可能方案 -------------- ...

随机推荐

  1. crontab日常使用梳理

    在日常的运维工作中,对crontab定时任务的制定是再寻常不过的了.根据以往的使用经验梳理如下: 基本格式 :* * * * * command分 时 日 月 周 命令解释:第1列表示分钟1-59 每 ...

  2. 【转】【MySQL】mysql 通过bin-log恢复数据方法详解

    mysql中bin-log在mysql默认状态下是没有打开的,我们要先打开mysql 开启bin-log功能,然后再通过备份的bin-log进行数据库恢复了. 具体的操作是通过mysqlbinlog这 ...

  3. 启动PPT的时候一直配置vs2013的问题解决

    前几天装了VS2013,结果发现每次启动powerpoint都要配置vs2013,虽然时间花的不多,可我看的就是碍眼,我都想把VS2013卸载来解决了.后来抱着试下的态度竟然在google上找到了解决 ...

  4. ASP.NET性能优化之减少请求

    在上篇<ASP.NET性能优化之让浏览器缓存动态网页> 中的方案中,浏览器发送If-Modified-Since将是否需要使用自己的缓存交给WEB服务器去决定,服务器告知浏览器去读缓存,浏 ...

  5. C#.NET 大型通用信息化系统集成快速开发平台 4.0 版本 - 独立子系统管理员功能实现

    1: 由于公司一次性要开发10多个子系统,每个子系统都需要有相关的业务部门进行对应.2: 若用集中式管理方式,每个业务部门人员变动,权限变动时,都需要早IT信息中心进行调整,影响工作效率.及时性.3: ...

  6. weblogic.nodemanager.common.ConfigException: Native version is enabled but nodemanager native library could not be loaded 解决办法

    近日在一个原本工作正常的weblogic web server(操作系统为redhat 64位系统)上折腾安装redis/hadoop等东东,yum install了一堆第3方类库后,重启weblog ...

  7. java:集合的自定义多重排序

    问题: 有一个乱序的对象集合,要求先按对象的属性A排序(排序规则由业务确定,非A-Z或0-9的常规顺序),相同A属性的记录,按根据属性B排序(排序规则,同样由业务确定,非常规顺序) -前提:业务规则是 ...

  8. ReactNative真机运行指南

    ReactNative真机运行指南 注意在iOS设备上运行React Native应用需要一个Apple Developer account并且把你的设备注册为测试设备.本向导只包含React Nat ...

  9. 使用mysqldump进行mysql数据库备份还原

    mysqldump是mysql自带的备份还原工具,默认在安装目录的bin下 可通过cmd命令行启动,然后运行: 还原一个数据库: mysql -h 主机 -u 用户名 -p密码 数据库名 < 指 ...

  10. Nodejs进阶:如何玩转子进程(child_process)

    本文摘录自个人总结<Nodejs学习笔记>,更多章节及更新,请访问 github主页地址.欢迎加群交流,群号 197339705. 模块概览 在node中,child_process这个模 ...