link

题意:

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

$n,m,s,q\leq 2\times 10^5.$

题解:

只有加油站是有用的点,问题可以转化为求一个加油站的排列,使得相邻两个加油站距离最大值小于等于油量上限。一个简单粗暴的想法是求出加油站两两最短路,然后直接上MST,离线处理询问。

其实上述的暴力做法是有很多冗余的(有很多边用不到)。考虑更优的建边方式。可以发现一个加油站每次往离他最近的加油站走最优(显然,不然为什么求的是MST)。我们将所有加油站扔进dijkstra里跑多源最短路,求出距离每个点最近的加油站,记为nearest[]。对于原图上一条边$u\sim v$,假如nearest[u]=nearest[v],那么这条边没有用;否则,建一条$nearest[u]\sim nearest[v]$的边,边权为dis(u,nearest[u])+dis(v,nearest[v])+dis(u,v)。相当于添加了一条nearest[u]到nearest[v]的路径(经过u-v这条边)。那么将所有原图的边遍历完之后,也恰好加入了所有可能在MST上的加油站之间的边。

那么再对这个新图跑MST,离线处理询问即可。复杂度$\mathcal{O}(n\log n+\alpha(m+q))$。

code:

 #include<bits/stdc++.h>
#define rep(i,x,y) for (int i=(x);i<=(y);i++)
#define ll long long
#define inf 1000000001
#define y1 y1___
#define pli pair<ll,int>
#define fi first
#define se second
using namespace std;
char gc(){
static char buf[],*p1=buf,*p2=buf;
return p1==p2&&(p2=(p1=buf)+fread(buf,,,stdin),p1==p2)?EOF:*p1++;
}
#define gc getchar
ll read(){
char ch=gc();ll x=;int op=;
for (;!isdigit(ch);ch=gc()) if (ch=='-') op=-;
for (;isdigit(ch);ch=gc()) x=(x<<)+(x<<)+ch-'';
return x*op;
}
#define N 200005
int n,k,m,x,cnt,head[N],nrst[N],fa[N];ll dis[N];bool vis[N];
struct edge{int to,nxt,w;}e[N<<];
struct ask{int x,y,w,id;}q[N];
struct node{
int x,y;ll w;node(){}
node(int x_,int y_,ll w_){x=x_,y=y_,w=w_;}
}a[N];
bool cmp_q(ask x,ask y){return x.w<y.w;}
bool cmp_a(node x,node y){return x.w<y.w;}
priority_queue<pli,vector<pli>,greater<pli> > q_;
void adde(int x,int y,int z){
e[++cnt].to=y;e[cnt].nxt=head[x];head[x]=cnt;
e[cnt].w=z;
}
void dij(){
while (!q_.empty()){
int u=q_.top().se;q_.pop();
if (vis[u]) continue;vis[u]=;
for (int i=head[u];i;i=e[i].nxt){
int v=e[i].to;
if (dis[v]>dis[u]+e[i].w)
dis[v]=dis[u]+e[i].w,q_.push(pli(dis[v],v)),nrst[v]=nrst[u];
}
}
}
void build(){
cnt=;
rep (u,,n) for (int i=head[u];i;i=e[i].nxt){
int v=e[i].to;
if (nrst[u]!=nrst[v]&&nrst[u]<nrst[v]) a[++cnt]=node(nrst[u],nrst[v],dis[u]+dis[v]+e[i].w);
}
}
int getfa(int x){return x==fa[x]?x:fa[x]=getfa(fa[x]);}
int main(){
n=read(),k=read(),m=read();
memset(dis,0x3f,sizeof(dis));
rep (i,,k){int x=read();dis[x]=,q_.push(pli(,x)),nrst[x]=x;}//nrst[x]:nearest(x),距离x最近的加油站
rep (i,,m){int x=read(),y=read(),z=read();adde(x,y,z);adde(y,x,z);}
dij();build();
m=read();
rep (i,,m) q[i].x=read(),q[i].y=read(),q[i].w=read(),q[i].id=i;
sort(&a[],&a[cnt+],cmp_a);sort(&q[],&q[m+],cmp_q);
rep (i,,n) fa[i]=i,vis[i]=;int j=;
rep (i,,m){
for (;j<=cnt&&a[j].w<=q[i].w;j++) fa[getfa(a[j].x)]=getfa(a[j].y);
if (getfa(q[i].x)==getfa(q[i].y)) vis[q[i].id]=;
}
rep (i,,m) puts(vis[i]?"TAK":"NIE");
return ;
}

bzoj4144 [AMPPZ2014]Petrol的更多相关文章

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

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

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

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

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

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

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

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

  5. BZOJ 4144: [AMPPZ2014]Petrol

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

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

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

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

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

  8. 【BZOJ】4144: [AMPPZ2014]Petrol

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

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

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

随机推荐

  1. 2017ACM暑期多校联合训练 - Team 7 1010 HDU 6129 Just do it (找规律)

    题目链接 Problem Description There is a nonnegative integer sequence a1...n of length n. HazelFan wants ...

  2. LintCode题解之子树

    思路: 最简单的方法,依次遍历比较就可以了. AC代码: /** * Definition of TreeNode: * public class TreeNode { * public int va ...

  3. nesC编程入门

    1.接口 NesC程序主要由各式组件(component)构成,组件和组件之间通过特定的接口(interface)互相沟通.一个接口内声明了提供相关服务的方法(C语言函数).例如数据读取接口(Read ...

  4. 42、和为S的两个数字

    一.题目 输入一个递增排序的数组和一个数字S,在数组中查找两个数,是的他们的和正好是S,如果有多对数字的和等于S,输出两个数的乘积最小的. 二.解法 import java.util.ArrayLis ...

  5. Linux线程编程之生产者消费者问题【转】

    转自:http://www.cnblogs.com/clover-toeic/p/4029269.html 前言 本文基于顺序循环队列,给出Linux生产者/消费者问题的多线程示例,并讨论编程时需要注 ...

  6. Codeforces Round #441 (Div. 2)

    Codeforces Round #441 (Div. 2) A. Trip For Meal 题目描述:给出\(3\)个点,以及任意两个点之间的距离,求从\(1\)个点出发,再走\(n-1\)个点的 ...

  7. JSOI 2017 Round 1滚粗记

    day0 到常州一中报道,吃了午饭,好像这次有小火锅. 然后下午听JYY讲线性规划...好神啊. 晚上去试机,机子上没有npp,只有linux下的codeblocks,敲起来一顿一顿的...后来被迫使 ...

  8. Java的BIO,NIO,AIO

    Java中的IO操作可谓常见.在Java的IO体系中,常有些名词容易让人困惑不解.为此,先通俗地介绍下这些名词. 1 什么是同步? 2 什么是异步? 3 什么是阻塞? 4 什么是非阻塞? 5 什么是同 ...

  9. 安全控制 iptables

    转自:http://www.opsers.org/linux-home/videos/chapter-netfilter-iptables-raiders.html 内容简介防火墙的概述iptable ...

  10. 转 proc文件

    /proc 是一个伪文件系统, 被用作内核数据结构的接口, 而不仅仅是解释说明/dev/kmem. /proc 里的大多数文件都是只读的, 但也可以通过写一些文件来改变内核变量. 下面对整个 /pro ...