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

n,m,q,s<=20W,b<=2e9。

标程:

 #include<cstdio>
#include<algorithm>
#include<queue>
#include<cstring>
using namespace std;
typedef long long ll;
int read()
{
int x=;char ch=getchar();
while (ch<''||ch>'') ch=getchar();
while (''<=ch&&ch<='') x=(x<<)+(x<<)+ch-'',ch=getchar();
return x;
}
const int N=;
const int inf=0x3f3f3f3f;
struct node{int to,next,w;}num[N*];
struct _node{int i;ll dis;_node(int A,ll B){i=A;dis=B;}};
struct Node{int u,v,id;ll dis;Node(){}; Node(int A,int B,ll C,int D){u=A;v=B;dis=C;id=D;}}a[N],e[N];
struct cmp{
bool operator () (const _node &A,const _node &B)
{return A.dis>B.dis;}
};
priority_queue<_node,vector<_node>,cmp>q;
int cnt,S,fa[N],u,v,w,n,s,m,head[N],vis[N],f[N],Q,ans[N],tot;
ll dis[N],b;
void add(int x,int y,int w)
{num[++cnt].to=y;num[cnt].next=head[x];num[cnt].w=w;head[x]=cnt;}
int find(int x) {return x==f[x]?x:f[x]=find(f[x]);}
bool operator < (const Node &A,const Node &B){return A.dis<B.dis;}
void dijk()
{
while (!q.empty())
{
_node now=q.top();q.pop();
if (vis[now.i]) continue;vis[now.i]=;
for (int i=head[now.i];i;i=num[i].next)
if (dis[num[i].to]>dis[now.i]+num[i].w)
{
dis[num[i].to]=dis[now.i]+num[i].w;q.push(_node(num[i].to,dis[num[i].to]));
fa[num[i].to]=fa[now.i];
}
}
}
void init()
{
for (int i=;i<=n;i++)
for (int j=head[i];j;j=num[j].next)
if (fa[i]!=fa[num[j].to]&&fa[i]<fa[num[j].to]) e[++tot]=Node(fa[i],fa[num[j].to],dis[i]+dis[num[j].to]+num[j].w,tot);
}
void mst()
{
int head=;
for (int i=;i<=n;i++) f[i]=i;
for (int i=;i<=Q;i++)
{
while (head<=tot&&e[head].dis<=a[i].dis)
{
int x=e[head].u,y=e[head].v;
if (find(x)!=find(y)) f[find(x)]=find(y);
head++;
}
if (find(a[i].u)!=find(a[i].v)) ans[a[i].id]=;else ans[a[i].id]=;
}
}
int main()
{
n=read();s=read();m=read();
memset(dis,inf,sizeof(dis));
for (int i=;i<=s;i++) S=read(),dis[S]=,q.push(_node(S,)),fa[S]=S;
for (int i=;i<=m;i++) u=read(),v=read(),w=read(),add(u,v,w),add(v,u,w);
dijk();init();
Q=read();
for (int i=;i<=Q;i++) a[i].u=read(),a[i].v=read(),a[i].dis=read(),a[i].id=i;
sort(a+,a+Q+);sort(e+,e+tot+);
mst();
for (int i=;i<=Q;i++) puts(ans[i]?"TAK":"NIE");
return ;
}

题解:并查集+技巧

要走到肯定是瞄准了加油站走。而且每次如果能走,往最近的加油站走答案一定不会变劣(你也可以走回来)。

那么就有一种高超的建图方法:

1.跑多源最短路,找到每个点离它最近的加油站,算出距离。

2.对于原图边(u,v),如果nearest[u]!=nearest[v],那么连边nearest[u]-nearest[v],边权为dist(u,nearest[u])+dist(v,nearest[v])+dist(u,v)。

这样离u,v最近的加油站就有经过(u,v)的一条路径了,但是不一定这样的dist(nearest[u],nearest[v])就是实际最短路,然而如果不是实际最短路,一定有另一个加油站k,离这边一个加油站更近,而且这样nearest[u]和nearest[v]一定通过另外几个加油站连通,实际走的策略也应该是经过另外几个加油站的。

离线掉询问按b从小到大排序,也按照b的顺序加入边,用并查集维护连通性。查询时,起点终点在同一个块中则可行。O((q+n)a)。

需要在线的话就构造出最小生成树,倍增/树剖找链上最大值。

bzoj4144 Petrol的更多相关文章

  1. 题解 [BZOJ4144] Petrol

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

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

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

  3. bzoj4144【AMPPZ2014】Petrol

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

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

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

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

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

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

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

  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

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

随机推荐

  1. LeetCode 181. Employees Earning More Than Their Managers (超过经理收入的员工)

    题目标签: 题目给了我们一个 员工表,包括经理.员工会有经理的id. 这里可以重复 利用两次 表格,表格a, 表格b,当a 员工的经理id  等于 b员工时候,在从中找到员工工资大于经理的.具体看co ...

  2. 新手git遇到的问题

    1. 如何撤销git add,不小心执行了git add . 操作,但是又不能提交所有的文件,因为对应不同的分支,现在怎么样可以将git add 撤销回来? 解决:git reset HEAD(暂时尝 ...

  3. 第四天:语句、表达式与if分支、循环语句

    表达式 代码风格 代码格式指南 PEP8 缩进4空格 一行不超过79 空行 赋值语句 基本 (x,y) = (5,10) x [x,y,z] = [1,2,3] x a,b,c = 'uhk' a 5 ...

  4. 17-MySQL-Ubuntu-数据表的查询-分页(六)

    分页(limit) 注: (1)limit位于SQL语句的最后面; (2)limit 2; 2表示查询前两条数据; (3)limit 0,2;  0表示查询第1页的起始数据的下标,2表示每页有两条数据 ...

  5. 2019 HDU 多校赛第二场 HDU 6598 Harmonious Army 构造最小割模型

    题意: 有n个士兵,你可以选择让它成为战士还是法师. 有m对关系,u和v 如果同时为战士那么你可以获得a的权值 如果同时为法师,你可以获得c的权值, 如果一个为战士一个是法师,你可以获得b的权值 问你 ...

  6. 转载:ASP.NET Core 在 JSON 文件中配置依赖注入

    在以前的 ASP.NET 4+ (MVC,Web Api,Owin,SingalR等)时候,都是提供了专有的接口以供使用第三方的依赖注入组件,比如我们常用的会使用 Autofac.Untiy.Stri ...

  7. vue3+node全栈项目部署到云服务器

    一.前言 最近在B站学习了一下全栈开发,使用到的技术栈是Vue+Element+Express+MongoDB,为了让自己学的第一个全栈项目落地,于是想着把该项目部署到阿里云服务器.经过网上一番搜索和 ...

  8. vue 报错:Cannot read property '__ob__' of undefined

    我的原因:引入组件后未注册 <script> import ComFirst from "../../components/ComFirst.vue" import C ...

  9. SHELL脚本中执行SQL语句操作MYSQL的5种方法

    对于自动化运维,诸如备份恢复之类的,DBA经常需要将SQL语句封装到shell脚本.本文描述了在Linux环境下mysql数据库中,shell脚本下调用sql语句的几种方法,供大家参考.对于脚本输出的 ...

  10. 转: https原理:证书传递、验证和数据加密、解密过程解析

    原本连接:http://www.cnblogs.com/zhuqil/archive/2012/07/23/2604572.html 我们都知道HTTPS能够加密信息,以免敏感信息被第三方获取.所以很 ...