博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
[AMPPZ2014]Petrol
阅读量:4364 次
发布时间:2019-06-07

本文共 2900 字,大约阅读时间需要 9 分钟。

题面

给定一个\(n\)个点、\(m\)条边的带权无向图,其中有\(s\)个点是加油站。

每辆车都有一个油量上限\(b\),即每次行走距离不能超过\(b\),但在加油站可以补满。
\(q\)次询问,每次给出\(x,y,b\),表示出发点是\(x\),终点是\(y\),油量上限为\(b\),且保证\(x\)点和\(y\)点都是加油站,请回答能否从\(x\)走到\(y\)

  • \(n,m,q\leq2*10^5\)

    解析

    其实如果这个图上只有加油站,那和\(noip2013\)货车运输是一道题。

    所以让我们把这个图简化成只有加油站的形式。

这要求我们求出图上加油站两两之间的距离。

然而不会饿。。。

(是同一个套路)

从每个加油站出发跑多源最短路(\(Dijstra\))。
如果一个点距离可以被更新,就更新,并标记离它最近的加油站。
否则,如果这个点被另一个加油站标记过,就说明这个点在当前加油站标记加油站的最短路径上,可以利用距离信息,在新图上为这两个加油站建边。

这样就简化完了。

然后在新图上求出最小生成树,询问用倍增+\(ST\)表处理即可。

#include
#include
#include
#include
#include
#include
#include
#define ll long long#define re register#define il inline#define pi pair
#define mk make_pair#define fp(i,a,b) for(re int i=a;i<=b;++i)#define fq(i,a,b) for(re int i=a;i>=b;--i)using namespace std;const int N=2e5+100;int n,m,h[N],cnt,dis[N],oil[N],tot,f[N],d[N],fa[18][N],st[18][N],q,top;bool vis[N];struct Edge{int to,nxt,w;}e[N<<1];struct dat{int u,v,w;il bool operator < (const dat &o) const {return w
<<1];il void add(re int u,re int v,re int w){e[++cnt]=(Edge){v,h[u],w};h[u]=cnt;}priority_queue
,greater
>Q;il int find(re int x){return x==f[x]?x:f[x]=find(f[x]);}il ll gi(){ re ll x=0,t=1; re char ch=getchar(); while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar(); if(ch=='-') t=-1,ch=getchar(); while(ch>='0'&&ch<='9') x=x*10+ch-48,ch=getchar(); return x*t;}il int max(re int x,re int y){return x>y?x:y;}il void dfs(re int u,re int ff){ d[u]=d[ff]+1; fp(i,1,17) fa[i][u]=fa[i-1][fa[i-1][u]],st[i][u]=max(st[i-1][u],st[i-1][fa[i-1][u]]); for(re int i=h[u];i+1;i=e[i].nxt) { re int v=e[i].to; if(v==ff) continue; fa[0][v]=u;st[0][v]=e[i].w; dfs(v,u); }}il int solve(re int u,re int v){ re int mx=0; if(d[u]
=d[v]) mx=max(mx,st[i][u]),u=fa[i][u]; if(u==v) return mx; fq(i,17,0) if(fa[i][u]^fa[i][v]) { mx=max(mx,st[i][u]);mx=max(mx,st[i][v]); u=fa[i][u];v=fa[i][v]; } mx=max(mx,st[0][u]);mx=max(mx,st[0][v]); return mx;}int main(){ memset(h,-1,sizeof(h));memset(dis,63,sizeof(dis)); n=gi();top=gi();m=gi(); fp(i,1,top) { re int x=gi(); oil[x]=x,dis[x]=0,Q.push(mk(0,x)); } fp(i,1,m) { re int u=gi(),v=gi(),w=gi(); add(u,v,w);add(v,u,w); } while(!Q.empty()) { re int u=Q.top().second;Q.pop(); if(vis[u]) continue;vis[u]=1; for(re int i=h[u];i+1;i=e[i].nxt) { re int v=e[i].to; if(dis[v]>dis[u]+e[i].w) dis[v]=dis[u]+e[i].w,oil[v]=oil[u],Q.push(mk(dis[v],v)); else if(oil[v]^oil[u]) a[++tot]=(dat){oil[u],oil[v],dis[u]+dis[v]+e[i].w}; } } sort(a+1,a+1+tot); memset(h,-1,sizeof(h));cnt=0; fp(i,1,n) f[i]=i; fp(i,1,tot) { re int u=a[i].u,v=a[i].v,w=a[i].w,fu=find(u),fv=find(v); if(fu^fv) { add(u,v,w);add(v,u,w); f[fv]=fu; } } fp(i,1,n) if(oil[i]==i&&!d[i]) dfs(i,0); q=gi(); while(q--) { re int u=gi(),v=gi(),lim=gi(); if(find(u)^find(v)) puts("NIE"); else puts((solve(u,v)<=lim?"TAK":"NIE")); } return 0;}

转载于:https://www.cnblogs.com/yanshannan/p/9794182.html

你可能感兴趣的文章
自然数幂和
查看>>
film history
查看>>
Fiddler的安装与使用(进阶篇)
查看>>
Linux权限_用户_和用户组
查看>>
C语言求S(n) = a+aa+aaa+aaaa+...+aa..a之值,其中a是一个数字,n表示a的位数例如:2+22+222+2222+22222(此时n=5),n和a都从键盘输入。...
查看>>
UI基础之UITableView案例微博----自定义cell利用代码
查看>>
jsf 博客文章 第一集
查看>>
JS命名规范
查看>>
Day 6-1计算机网络基础&TCP/IP
查看>>
Django 入门案例开发
查看>>
TP里where的查询方式,比如or应该怎么写?
查看>>
spring注解说明之Spring2.5 注解介绍(3.0通用)
查看>>
【转载】android笔记--Intent和IntentFilter详解
查看>>
php提供图片下载的方法
查看>>
使用Keil下载单独的Hex文件到单片机内
查看>>
EditPlus中文版 安装教程
查看>>
ASP.NET MVC4使用JCrop裁剪图片并上传
查看>>
poj1564
查看>>
string类的常用的几个小东西find,substr
查看>>
玲珑OJ1088【蜜汁尺取】
查看>>