二分答案+堆优Dijkstra

  • 这个题有些巧妙。
  • 首先,因为要在油量耗完之前跑到终点,所以我们可以用最短路。只要从\(s\)出发到\(t\),它的最短距离大于油量,我们就可以断定它一定走不通,直接输出\(-1\)。
  • 然后因为要求最大值最小,所以考虑二分答案。用一个数组来储存点的值从大到小的排序,然后边界范围设置 : \(L\)为\(s\)和\(t\)的中较大的拿一个的排名,\(R\)为n。为什么\(L\)要这样设置呢?因为\(s\)和\(t\)是必经的点,所以它们一定要选,所以最小值只能设为它们之间较大的一个。
  • 但是在存边的时候要注意,没有必要判重!!!因为两条路,他们连接的点可能一样,但是他们的距离不同,所以判重还会导致花费更多没必要的时间。我就是被说明给坑了。。。
  • 上代码,有不清楚的代码里面尽量写明。
#include<bits/stdc++.h>
#define clean(a,i) memset(a,i,sizeof(a))
#define ll long long
#define inl inline
#define il inl void
#define it inl int
#define ill inl ll
#define re register
#define ri re int
#define rl re ll
#define mid ((l+r)>>1)
using namespace std;
template<class T>il read(T &x) //快读
{
int f=1;char k=getchar();x=0;
for(;k>'9'||k<'0';k=getchar()) if(k=='-') f=-1;
for(;k>='0'&&k<='9';k=getchar()) x=(x<<3)+(x<<1)+k-'0';
x*=f;
}
const int MAXN = 1e4+5,MAXM= 5e4+5;
int n,m,s,t,mx,u,v,d,num_edge,head[MAXN],val[MAXN],p[MAXN],dis[MAXN],l,r; //p数组用来存每个点的权值排序后的顺序
struct Edge{
int next,to,dis;
Edge(){}
Edge(int next,int to,int dis):next(next),to(to),dis(dis){}
}edge[MAXM<<1]; //加边,无向边开两倍
il add_edge(int u,int v,int dis){
edge[++num_edge]=Edge(head[u],v,dis);head[u]=num_edge;
edge[++num_edge]=Edge(head[v],u,dis);head[v]=num_edge;
} //用结构体的生成函数写,方便又简洁
struct Node{
int dis,pos;
Node(){}
Node(int dis,int pos):dis(dis),pos(pos){}
bool operator <(const Node &t) const{
return dis>t.dis;
}
}; //用来跑Dijkstra,堆优要用
bool tr[MAXN]; //判断是否用这个点松弛过
il dijkstra(int lim){ //lim用来限制通过的点的最大权值
priority_queue<Node> q;q.push(Node(0,s));
clean(tr,0);clean(dis,0x3f);dis[s]=0; //初始化
while(!q.empty()){
Node tmp=q.top();q.pop();
ri pos=tmp.pos;
if(tr[pos]||val[pos]>lim) continue;
tr[pos]=true;
for(ri i=head[pos];i;i=edge[i].next){
if(dis[edge[i].to]>dis[pos]+edge[i].dis){
dis[edge[i].to]=dis[pos]+edge[i].dis;
if(!tr[edge[i].to]) q.push(Node(dis[edge[i].to],edge[i].to));
}
}
}
} //这个基本是堆优Dijkstra的模板,当然,在写法上可能有不同,不会的小伙伴可以去看一下 P4779 【模板】单源最短路径(标准版)
int main()
{
// freopen(".in","r",stdin);
// freopen(".out","w",stdout);
read(n),read(m),read(s),read(t),read(mx); //读入
for(ri i=1;i<=n;i++) read(val[i]),p[i]=val[i];
for(ri i=1;i<=m;i++){
read(u),read(v),read(d);
if(d>mx) continue;
add_edge(u,v,d);
} //加边
sort(p+1,p+1+n); //给每个点的权值排序
dijkstra(p[n]); //先用最大的跑一遍,如果走不通,说明无解
if(dis[t]>mx){
printf("-1");
return 0;
}
for(ri i=1;i<=n;i++) if(p[i]==max(val[s],val[t])) {l=i;break;} //确定l的取值
r=n;
while(l<r){ //二分答案
dijkstra(p[mid]);
if(dis[t]>mx) l=mid+1;
else r=mid;
}
printf("%d",p[l]); //输出
return 0;
}
  • 愉快收工!![]( ̄▽ ̄)*

顺便安利一下自己的博客 虽然还几乎啥都没有

Luogu P1951 收费站_NOI导刊2009提高(2)的更多相关文章

  1. luogu P1951 收费站_NOI导刊2009提高(2) |二分答案+最短路

    题目描述 在某个遥远的国家里,有n个城市.编号为1,2,3,-,n. 这个国家的政府修建了m条双向的公路.每条公路连接着两个城市.沿着某条公路,开车从一个城市到另一个城市,需要花费一定的汽油. 开车每 ...

  2. Luogu P1951 收费站_NOI导刊2009提高(2) 二分 最短路

    思路:二分+最短路 提交:1次 题解: 二分最后的答案. $ck()$: 对于每次的答案$md$跑$s,t$的最短路,但是不让$c[u]>md$的点去松弛别的边,即保证最短路不经过这个点.最后$ ...

  3. 洛谷 P1951 收费站_NOI导刊2009提高(2) 最短路+二分

    目录 题面 题目链接 题目描述 输入输出格式 输入格式 输出格式 输入输出样例 输入样例: 输出样例: 说明 思路 AC代码 总结 题面 题目链接 P1951 收费站_NOI导刊2009提高(2) 其 ...

  4. 洛谷——P1951 收费站_NOI导刊2009提高(2)

    https://www.luogu.org/problem/show?pid=1951 题目描述 在某个遥远的国家里,有n个城市.编号为1,2,3,…,n. 这个国家的政府修建了m条双向的公路.每条公 ...

  5. 洛谷 P1951 收费站_NOI导刊2009提高(2)

    题目描述 在某个遥远的国家里,有n个城市.编号为1,2,3,…,n. 这个国家的政府修建了m条双向的公路.每条公路连接着两个城市.沿着某条公路,开车从一个城市到另一个城市,需要花费一定的汽油. 开车每 ...

  6. [洛谷P1951]收费站_NOI导刊2009提高(2)

    题目大意:有一张$n$个点$m$条边的图,每个点有一个权值$w_i$,有边权,询问从$S$到$T$的路径中,边权和小于$s$,且$\max\limits_{路径经过k}\{w_i\}$最小,输出这个最 ...

  7. 题解 P1951 【收费站_NOI导刊2009提高(2)】

    查看原题请戳这里 核心思路 题目让求最大费用的最小值,很显然这道题可以二分,于是我们可以二分花费的最大值. check函数 那么,我们该怎么写check函数呢? 我们可以删去费用大于mid的点以及与其 ...

  8. 洛谷1462(重题1951) 通往奥格瑞玛的道路(收费站_NOI导刊2009提高(2))

    1462原题链接 1951原题链接 显然答案有单调性,所以可以二分答案,用\(SPFA\)或\(dijkstra\)跑最短路来判断是否可行即可. 注意起点也要收费,\(1462\)数据较水,我一开始没 ...

  9. 洛谷 P1952 火星上的加法运算_NOI导刊2009提高(3)

    P1952 火星上的加法运算_NOI导刊2009提高(3) 题目描述 最近欢欢看到一本有关火星的书籍,其中她被一个加法运算所困惑,由于她的运算水平有限.她想向你求助,作为一位优秀的程序员,你当然不会拒 ...

随机推荐

  1. 区块链相关在线加解密工具(非对称加密/hash)

    https://cse.buffalo.edu/blockchain/tools.html https://cse.buffalo.edu/blockchain/encryption.html 由纽约 ...

  2. Android 禁止屏幕旋转 & 旋转屏幕时保持Activity内容

    Android 禁止屏幕旋转 & 旋转屏幕时保持Activity内容   1.在应用中固定屏幕方向.        在AndroidManifest.xml的activity中加入:     ...

  3. 为什么不加WWW的域名能访问,前面加了WWW后不能访问?

    解决方法:我的主机记录没有添加www,添加后就可以访问了

  4. python的return

    关于python的return用法,在stackoverflow里的问题: Python — return, return None, and no return at all Consider th ...

  5. UVa 12093 Protecting Zonk (树形DP)

    题意:给定一个有n个节点的无根树,有两种装置A和B,每种都有无限多个.在某个节点X使用A装置需要C1的花费,并且此时与节点X相连的边都被覆盖.在某个节点X使用B装置需要C2的花费,并且此时与节点X相连 ...

  6. c+内存管理机制

    内存管理是C++最令人切齿痛恨的问题,也是C++最有争议的问题,C++高手从中获得了更好的性能,更大的自由,C++菜鸟的收获则是一遍一遍的 检查代码和对C++的痛恨,但内存管理在C++中无处不在,内存 ...

  7. HRBUST1310 火影忍者之~鸣人 2017-03-06 16:01 104人阅读 评论(0) 收藏

    火影忍者之-鸣人 火影忍者的男主角漩涡鸣人,因为身上封印着邪恶的九尾妖狐,无父无母的他受尽了村人的冷眼与歧视,他下定决心要成为第六代火影,让所有人都认同他的存在,火影是动漫火影忍者中主人公鸣人所在的国 ...

  8. 基于Extjs的web表单设计器 第三节——控件拖放

    看过之前设计器截图的朋友应该有印象,可能会发觉我们的设计器UI设计布局其实类似Visual studio 的设计界面,采用的是左.中.右三个区域布局.左侧为控件区域.中间为表单的画布设区域.右侧为属性 ...

  9. [Erlang36]kerl轻松管理安装各种OTP版本

    kerl只有一个目标:让我们在不同的OTP版本间随意切换.他是一个纯Bash项目.简单实用的工作利器! Readme里面用法已说明得非常清楚了.建议按流程来一次. 1.下载 安装(一个bash脚本,根 ...

  10. Solr相似度算法二:Okapi BM25

    地址:https://en.wikipedia.org/wiki/Okapi_BM25   In information retrieval, Okapi BM25 (BM stands for Be ...