4144: [AMPPZ2014]Petrol

Time Limit: 10 Sec  Memory Limit: 256 MB
Submit: 752  Solved: 298
[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

鸣谢Claris上传


朴素是先写个多源最短路把加油站的最小生成树所有可能边弄出来,然后后面按部就班地建个最小生成树,然后对树上写个主席树(st倍增)找u到v上最大值,和b比较一下。

那我们在把所有可能边弄出来以后停一下2333,我们连边不要对这条边俩端点连,而是对他们所在块的堆头节点连,这个建出来在查询最大值上是等效的。然后我们启发式地合并堆,这样可以把堆高度控制在logn,就不用再写个主席树啥的那麻烦了。直接两个端点往上一个一个跳,logn的不会有事的。

 #include<bits/stdc++.h>
#define clr(x) memset(x,0,sizeof(x))
#define clr_1(x) memset(x,-1,sizeof(x))
#define INF 0x3f3f3f3f
#define LL long long
#define pb push_back
#define mod 1000000007
#define ls(i) (i<<1)
#define rs(i) (i<<1|1)
#define mp make_pair
#define fi first
#define se second
using namespace std;
typedef pair<LL,int > pli;
const int N = 2e5+;
bool need[N];
vector<pli> e[N];
struct node
{
int u,v;
LL w;
node(int _u=,int _v=,LL _w=):u(_u),v(_v),w(_w) {}
};
vector<node> ve;
int n,s,m,T;
priority_queue<pli,vector<pli>,greater<pli> > que;
int fuel[N];
int fa[N],rfa[N],rk[N],dep[N];
LL dis[N],val[N];
bool vis[N];
int pre[N];
void dij()
{
while(!que.empty())
{
pli now=que.top();
que.pop();
LL dist=now.fi;
int u=now.se;
if(vis[u]) continue;
vis[u]=;
int sz=e[u].size();
for(int i=;i<sz;i++)
{
pli p=e[u][i];
int w=p.fi;
int v=p.se;
if(!pre[v] || dis[v]>dis[u]+w)
{
dis[v]=dis[u]+w;
pre[v]=pre[u];
que.push(mp(dis[v],v));
}
else if(pre[u] != pre[v])
ve.pb(node(pre[u],pre[v],dis[u]+dis[v]+w));
}
}
return ;
}
bool cmp(node a,node b)
{
return a.w<b.w;
}
int Find(int u)
{
if(fa[u]!=u)
fa[u]=Find(fa[u]);
return fa[u];
}
void Union()
{
sort(ve.begin(),ve.end(),cmp);
for(int i=;i<=s;i++)
{
fa[fuel[i]]=fuel[i];
rk[fuel[i]]=;
}
int sz=ve.size();
for(int i=;i<sz;i++)
{
node p=ve[i];
int u = p.u, v = p.v;
LL w = p.w;
u = Find(u), v = Find(v);
if(u==v) continue;
if(rk[u]<rk[v]) swap(u,v);
if(rk[u]==rk[v]) rk[u]++;
rfa[v]=u,fa[v]=u,val[v]=w;
}
return ;
}
void dealdep(int u)
{
if(dep[u]>) return ;
if(fa[u]==u)
{
dep[u]=;
return ;
}
dealdep(rfa[u]);
dep[u]=dep[rfa[u]]+;
return ;
}
bool solve(int u,int v,LL b)
{
if(Find(u)!=Find(v)) return ;
if(dep[u]<dep[v]) swap(u,v);
while(dep[u]>dep[v])
{
if(b<val[u]) return ;
u=rfa[u];
}
if(u==v) return ;
while(u!=v)
{
if(b<val[u]) return ;
if(b<val[v]) return ;
u=rfa[u];
v=rfa[v];
}
return ;
}
int main()
{
scanf("%d%d%d",&n,&s,&m);
clr_1(dis);
for(int i=;i<=s;i++)
{
scanf("%d",fuel+i);
que.push(mp(,fuel[i]));
pre[fuel[i]]=fuel[i];
dis[fuel[i]]=;
}
for(int i=;i<=m;i++)
{
int u,v;
LL w;
scanf("%d%d%lld",&u,&v,&w);
e[u].pb(mp(w,v));
e[v].pb(mp(w,u));
}
dij();
Union();
for(int i=;i<=s;i++)
dealdep(fuel[i]);
int u,v;
LL b,maxn;
int q;
scanf("%d",&q);
while(q--)
{
scanf("%d%d%lld",&u,&v,&b);
if(solve(u,v,b))
printf("TAK\n");
else
printf("NIE\n");
}
return ;
}

4144: [AMPPZ2014]Petrol (多源最短路+最小生成树+启发式合并)的更多相关文章

  1. bzoj 4242 水壶 (多源最短路+最小生成树+启发式合并)

    4242: 水壶 Time Limit: 50 Sec  Memory Limit: 512 MBSubmit: 1028  Solved: 261[Submit][Status][Discuss] ...

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

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

  3. BZOJ 4144: [AMPPZ2014]Petrol

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

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

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

  5. 【BZOJ】4144: [AMPPZ2014]Petrol

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

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

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

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

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

  8. [AMPPZ2014]Petrol

    关键点的最小生成树? 关键点初始化为0,跑多源最短路,然后重构整个图,用Kruskal跑最小生成树 然后跑树链剖分在线回答询问 对树上每个点维护到链顶的最大值,结合线段树可以做到\(\Theta(n ...

  9. Day3 最短路 最小生成树 拓扑排序

    Day3 最短路 最小生成树 拓扑排序 (一)最短路 一.多源最短路 从任意点出发到任意点的最短路 1. Floyd \(O(n^3)\) for(int k=1;k<=n;k++) for(i ...

随机推荐

  1. java 一个函数如何返回多个值

    在开发过程中,经常会有这种情况,就是一个函数需要返回多个值,这是一个问题!! 网上这个问题的解决方法: 1.使用map返回值:这个方法问题是,你并不知道如何返回值的key是什么,只能通过doc或者通过 ...

  2. RocketMQ使用

    RocketMQ是阿里巴巴在2012年开源的分布式消息中间件,目前已经捐赠给Apache基金会,并于2016年11月成为 Apache 孵化项目. 中间件是一类连接软件组件和应用的计算机软件,它包括一 ...

  3. IIS 启用https

    参考:http://www.cnblogs.com/dudu/p/iis_https_ca.html

  4. (一)问候 Log4j 你好

    第一节: Log4j 简介 Log4j -------- log for java(java的日志) 是java主流的日志框架,提供各种类型,各种存储,各种格式,多样化的日志服务: 在爬虫领域,主要用 ...

  5. SQlserver创建函数实现只取某个字段的数字部分

    create FUNCTION [dbo].[GET_NUMBER](@S VARCHAR(100)) RETURNS VARCHAR(100) AS BEGIN WHILE PATINDEX('%[ ...

  6. Kubernetes 部署kafka ACL(单机版)

    一.概述 在Kafka0.9版本之前,Kafka集群时没有安全机制的.Kafka Client应用可以通过连接Zookeeper地址,例如zk1:2181:zk2:2181,zk3:2181等.来获取 ...

  7. MySQL 连接本地数据库、远程数据库命令

    一.MySQL 连接本地数据库,用户名为“root”,密码“123”(注意:“-p”和“123” 之间不能有空格) C:/>mysql -h localhost -u root -p123 二. ...

  8. 20155225 实验二《Java面向对象程序设计》实验报告

    20155225 实验二<Java面向对象程序设计>实验报告 一.单元测试 三种代码 知道了伪代码.产品代码.测试代码的关系和用途,并根据老师的例子,按测试代码调试了产品代码. 值得注意的 ...

  9. Java深度复制List内容。

    最近在工作的时候,有一个小需求,需要复制List的内容,然后会改变其中的数据,但是试了几种复制的方法,都是将原有的数据和复制后的数据都改变了,都没有达到我想要的效果. 其中涉及到了 "浅复制 ...

  10. C#基础系列 - 抽象类及其方法的学习

    在C#中使用关键字 abstract 来定义抽象类和抽象方法. 不能初始化的类被叫做抽象类,它们只提供部分实现,但是另一个类可以继承它并且能创建它们的实例. "一个包含一个或多个纯虚函数的类 ...