题目描述

​ 有一张 n 个点 m 条边的无向图,其中有 s 个点上有加油站。有 Q 次询问(a,b,c), 问能否开一辆油箱容积为 c 的车从 a 走到 b.(a,b均为加油站)

输入格式

​ 第一行三个整数 n,s,m。

​ 接下来一行 s 个数,表示有加油站的节点。

​ 接下来 m 行,每行三个整数 (x,y,z),表示一条连接 x,y,权值为 z 的边。

​ 接下来一行一个整数 Q。

​ 接下来 Q 行,每行三个整数 (a,b,c),表示询问。

输出格式

​ 共 Q 行,若对应询问可行,输出 "TAK",否则输出 "NIE"。

样例输入

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

样例输出

TAK

TAK

TAK

NIE

数据范围

​ Part 1:2 个测试点,每个 5 分:\(n,Q\leq100\)

​ Part 2:1 个测试点,20 分:\(n\leq1000\)

​ Part 3:2 个测试点,每个 10 分:\(n=s\)

​ Part 4:10 个测试点,每个 5 分:无特殊性质

​ 对于所有数据,\(2\leq s\leq n\leq200000,1\leq m\leq 200000,z\leq10000,c\leq2*10^9\)

解析

因为到加油站就能加满油了,

所以我们只需要满足油箱里的油能开到下一个加油站就行了,

也就是说,我们只需要将\(a\),\(b\)两地的路径分成若干段加油站到加油站的路径,

如果最大值小于等于容量\(C\)就能到达.

那么,我们就可以把加油站拿出来建一个最小生成树,

然而,怎么建啊?

暴力两两连边?

然后就\(TLE+MLE\)了...

其实,我们可以先求出离每个点\(i\)最近的加油站\(w[i]\)和距离\(d[j]\),

然后对于原图中的每条边\(x\),\(y\),

如果\(w[x]!=w[y]\),就把\(w[x],w[y]\)连一条边,

距离就是\(d[x]+d[y]+w_{x,y}\).

而\(w[i],d[i]\)怎么求呢?

跑多源SPFA就行啦.

然而到这里就完了吗?

其实我们还可以让代码更简单一些.

因为只需要判断连通性,

所以我们可以先将询问按容量排序,

再一边加边,用并查集维护连通块就行了.

code:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
#include <algorithm>
#define fre(x) freopen(x".in","r",stdin),freopen(x".out","w",stdout)
using namespace std; inline int read(){
int sum=0,f=1;char ch=getchar();
while(ch>'9' || ch<'0'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0' && ch<='9'){sum=sum*10+ch-'0';ch=getchar();}
return f*sum;
} const int N=400001;
struct edge{int to,next,w;}e[N<<1];
struct ques{int x,y,w,id;}q[N],E[N<<1],A[N<<1];
int n,s,m,Q,a[N],isoil[N],dep[N];
int head[N],cnt=0,Head[N],Cnt=0;
int w[N],d[N],v[N],ans[N];
int da[N],f[N][21],fa[N][21];
queue <int> que; bool cmp(ques a,ques b){return a.w<b.w;} inline void add(int x,int y,int w){
e[++cnt]=(edge){head[x],y,w};head[x]=cnt;
} inline void spfa(){
memset(d,0x3f,sizeof(d));
for(int i=1;i<=s;i++) que.push(a[i]),d[a[i]]=0,w[a[i]]=a[i],v[a[i]]=1;
while(!que.empty()){
int x=que.front();que.pop();
for(int i=head[x];i;i=e[i].to){
int k=e[i].next;
if(d[k]<=d[x]+e[i].w) continue;
d[k]=d[x]+e[i].w;w[k]=w[x];
if(!v[k]) v[k]=1,que.push(k);
}
v[x]=0;
}
} inline int find_fa(int x){return x==da[x]? x:da[x]=find_fa(da[x]);} inline void link(int i){
int a=find_fa(E[i].x),b=find_fa(E[i].y);
if(a!=b) da[a]=b;
} int main(){
n=read();s=read();m=read();
for(int i=1;i<=s;i++) a[i]=read(),isoil[a[i]]=1;
for(int i=1;i<=n;i++) da[i]=i;
for(int i=1;i<=m;i++){
A[i].x=read();A[i].y=read();A[i].w=read();
add(A[i].x,A[i].y,A[i].w);add(A[i].y,A[i].x,A[i].w);
}
spfa();
for(int i=1;i<=m;i++){
int x=A[i].x,y=A[i].y;
if(w[x]!=w[y]) E[++Cnt]=(ques){w[x],w[y],d[x]+d[y]+A[i].w};
}
Q=read();int tot=1;
for(int i=1;i<=Q;i++) q[i].x=read(),q[i].y=read(),q[i].w=read();
for(int i=1;i<=Q;i++) q[i].id=i;
sort(q+1,q+Q+1,cmp);sort(E+1,E+Cnt+1,cmp);
for(int i=1;i<=Q;i++){
while(E[tot].w<=q[i].w&&tot<=Cnt) link(tot++);
int a=find_fa(q[i].x),b=find_fa(q[i].y);
if(a==b) ans[q[i].id]=1;
}
for(int i=1;i<=Q;i++) puts(ans[i]? "TAK":"NIE");
return 0;
}

题解 [BZOJ4144] Petrol的更多相关文章

  1. [题解] [BZOJ4144] 「AMPPZ2014」Petrol

    题面 怎么是权限题啊 题解 有一次考过, 但是不记得了 如果每个点都是加油站的话, 这道题就是货车运输 考虑如何转化 我们可以设

  2. bzoj4144 Petrol

    题意:给你一张n个点m条边的带权无向图.其中由s个点是加油站.询问从x加油站到y加油站,油箱容量<=b,能否走到? n,m,q,s<=20W,b<=2e9. 标程: #include ...

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

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

  4. bzoj4144【AMPPZ2014】Petrol

    题解:  首先注意到起点和终点都是加油站;          假设中途经过某个非加油站的点u,u连到v,离u最近的加油站是x,那么从u到x加油后回到u,再到v一定不比直接从u到v差:        因 ...

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

    题目链接 BZOJ4144 题解 这题好妙啊,,orz 假设我们在一个非加油站点,那么我们一定是从加油站过来的,我们剩余的油至少要减去这段距离 如果我们在一个非加油站点,如果我们到达不了任意加油站点, ...

  6. 【BZOJ4144】[AMPPZ2014]Petrol(最短路+最小生成树+并查集)

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

  7. BZOJ4144: [AMPPZ2014]Petrol(最短路 最小生成树)

    题意 题目链接 Sol 做的时候忘记写题解了 可以参考这位大爷 #include<bits/stdc++.h> #define Pair pair<int, int> #def ...

  8. bzoj4144 [AMPPZ2014]Petrol

    link 题意: 给一个n个点m条边的带权无向图,其中k个点是加油站,每个加油站可以加满油,但不能超过车的油量上限.有q个询问,每次给出x,y,b,保证x,y都是加油站,问一辆油量上限为b的车从x出发 ...

  9. [BZOJ4144][AMPPZ2014]Petrol[多源最短路+MST]

    题意 题目链接 分析 假设在 \(a \rightarrow b\) 的最短路径中出现了一个点 \(x\) 满足到 \(x\) 最近的点是 \(c\) ,那么我们完全可以从 \(a\) 直接走到 \( ...

随机推荐

  1. kafka server.properties 配置文件详解(二)

    虽然在前面一部分我们启动了kafka集群,并通过控制台的方式实现了producer和consumer,但是我们还是了解一下kafka单个节点是的配置参数属性, 也只有了解了这些参数的配置,才能将kaf ...

  2. fiddler笔记:快捷工具栏

    WinConfig:   Comment 为所有选中的Session添加Comment. Replay Replay+ctrl 重新发送请求,而不包括任何条件请求头. Replay+shift 指定每 ...

  3. 【bitset】Kth Minimum Clique

    #include<bits/stdc++.h> #define B bitset<105> using namespace std; typedef long long ll ...

  4. 不吹不黑,赞一下应用运维管理的cassacdra

    不吹不黑的为菊厂的应用运维管理AOM点个赞.Why? 某菊厂应用运维管理工具AOM每天处理着亿级条数据,这么多数据是怎么存储的呢? 说到数据存储就会想到关系型数据库,比如mysql,oracle,sy ...

  5. java中的exception stack有时候不输出的原因

    有时候,我们在看java错误日志时,只看到一个java.lang.NullPointerException,却没有看到错误的栈,原因是启动时候有一项参数可以选择配置:OmitStackTraceInF ...

  6. 搭建Leanote网络云笔记

    下载启动 MongoDB Leanote 依赖 MongoDB 作为数据存储,下面开始安装 MongoDB: 下载 MongoDB 进入 /home 目录,并下载 MongoDB: cd /home ...

  7. hdu 2610 2611 dfs的判重技巧

    对于全排列枚举的数列的判重技巧 1:如果查找的是第一个元素 那么 从0开始到当前的位置看有没有出现过这个元素 出现过就pass 2: 如果查找的不是第一个元素 那么 从查找的子序列当前位置的前一个元素 ...

  8. 阿里云=>RHSA-2019:1884-中危: libssh2 安全更新

    由于项目构建时间比较长,近期安全检查发现openssh有漏洞.所以要升级openssh到7.9p1版本.由于ssh用于远程连接,所以要谨慎操作. 建议生成环境要先做测试,之后再在生产环境升级. 1 前 ...

  9. python numpy array 的sum用法

    如图: sum可以指定在那个轴进行求和: 且第0轴是纵向,第一轴是横向:

  10. 二元变量图形的pandas方法

    数据加载: 1.散点图 上图使用下采样的方法选取了100个样本点,因为把所有的数据加载进来太多了. 2.Hexplot图 上图是一个散点图再加上热力标注的形式,可以更准确的帮助我们看出数据集中在哪些区 ...