spfa进阶使用二分+SLF(洛谷1951 收费站_NOI导刊2009提高(2))

在某个遥远的国家里,有n个城市。编号为1,2,3,…,n。

这个国家的政府修建了m条双向的公路。每条公路连接着两个城市。沿着某条公路,开车从一个城市到另一个城市,需要花费一定的汽油。

开车每经过一个城市,都会被收取一定的费用(包括起点和终点城市)。所有的收费站都在城市中,在城市间的公路上没有任何的收费站。

小红现在要开车从城市u到城市v(1<=u,v<=n)。她的车最多可以装下s升的汽油。在出发的时候,车的油箱是满的,并且她在路上不想加油。

在路上,每经过一个城市,她都要交一定的费用。如果某次交的费用比较多,她的心情就会变得很糟。所以她想知道,在她能到达目的地的前提下,她交的费用中最多的一次最少是多少。这个问题对于她来说太难了,于是她找到了聪明的你,你能帮帮她吗?

输入格式:

第一行5个正整数,n,m,u,v,s,分别表示有n个城市,m条公路,从城市u到城市v,车的油箱的容量为s升。

接下来的有n行,每行1个整数,fi表示经过城市i,需要交费fi元。

再接下来有m行,每行3个正整数,ai,bi,ci(1<=ai,bi<=n),表示城市ai和城市bi之间有一条公路,如果从城市ai到城市bi,或者从城市bi到城市ai,需要ci升的汽油。

输出格式:

仅一个整数,表示小红交费最多的一次的最小值。

如果她无法到达城市v,输出-1.

输入样例#1:

4 4 2 3 8
8
5
6
10
2 1 2
2 4 1
1 3 4
3 4 3

输出样例#1:

8
  1 #include<iostream>
  2 #include<algorithm>
  3 #include<cmath>
  4 #include<cstring>
  5 #include<cstdio>
  6 #include<queue>
  7 #define maxn 150000
  8 #define LL long long
  9
 10 using namespace std;
 11 LL  n,m,u,v,s;
 12
 13 struct Edge
 14 {
 15    LL  next,to,w;
 16 };
 17 struct Edge edge[maxn];
 18 LL  cnt=0;
 19 LL  head[maxn];
 20 LL val[maxn];
 21
 22 void add(LL  u,LL  v,LL  ww)
 23 {
 24     edge[++cnt].to=v;
 25     edge[cnt].w=ww;
 26     edge[cnt].next=head[u];
 27     head[u]=cnt;
 28 }
 29
 30 deque<LL> q;//双向队列
 31 LL  book[maxn],dis[maxn];
 32
 33 int  spfa(LL  x)//最大的价值
 34 {
 35        if(val[u]>x||val[v]>x) return 0;//剪枝
 36        memset(book,0,sizeof(book));
 37
 38         for(LL  i=1;i<=n;i++)
 39              dis[i]=1e12;
 40
 41           book[u]=1;dis[u]=0;
 42           q.push_back(u);
 43
 44           while(!q.empty())
 45           {
 46               LL  fr=q.front();
 47               book[fr]=0;q.pop_front();
 48               for(LL i=head[fr];i;i=edge[i].next)
 49               {
 50                    LL  j=edge[i].to;
 51                    if(val[j]>x) continue;
 52                    if(dis[j]>dis[fr]+edge[i].w)
 53                    {
 54                        dis[j]=dis[fr]+edge[i].w;
 55                        if(!book[j])
 56                        {
 57                            if(q.empty()) q.push_back(j);
 58                            else
 59                            {
 60                               if(dis[j]<dis[q.front()])
 61                                   q.push_front(j);//在前部插入
 62                                  else
 63                                    q.push_back(j);
 64                            }
 65                            book[j]=1;//标记已经入队
 66                        }
 67                    }
 68               }
 69           }
 70           if(dis[v]<=s) return 1;
 71          return 0;
 72 }
 73
 74
 75 int  main()
 76 {     LL  l=1,r=0;
 77     cin>>n>>m>>u>>v>>s;
 78     for(LL  i=1;i<=n;i++)
 79     {
 80        cin>>val[i];
 81        r=max(val[i],r);
 82     }
 83        LL  t1,t2,t3;
 84     for(LL  i=1;i<=m;i++)
 85     {
 86        cin>>t1>>t2>>t3;
 87        add(t1,t2,t3);
 88        add(t2,t1,t3);
 89     }
 90     if(!spfa(1e13))
 91     {
 92       cout<<-1;
 93       return 0;
 94     }
 95     while(l<=r)
 96     {
 97         LL  mid=(l+r)>>1;
 98         if(spfa(mid))r=mid-1;
 99         else l=mid+1;
100     }
101     cout<<l<<endl;
102    return 0;
103 }

90分的代码,还需要优化

时间: 2024-09-30 00:56:31

spfa进阶使用二分+SLF(洛谷1951 收费站_NOI导刊2009提高(2))的相关文章

堆or优先队列(洛谷1801 黑匣子_NOI导刊2010提高(06))

Black Box是一种原始的数据库.它可以储存一个整数数组,还有一个特别的变量i.最开始的时候Black Box是空的.而i等于0.这个Black Box要处理一串命令. 命令只有两种: ADD(x):把x元素放进BlackBox; GET:i加1,然后输出Blackhox中第i小的数. 记住:第i小的数,就是Black Box里的数的按从小到大的顺序排序后的第i个元素.例如: 我们来演示一下一个有11个命令的命令串.(如下图所示) 现在要求找出对于给定的命令串的最好的处理方法.ADD和GET

洛谷P1801 黑匣子_NOI导刊2010提高(06)

P1801 黑匣子_NOI导刊2010提高(06) 题目描述 Black Box是一种原始的数据库.它可以储存一个整数数组,还有一个特别的变量i.最开始的时候Black Box是空的.而i等于0.这个Black Box要处理一串命令. 命令只有两种: ADD(x):把x元素放进BlackBox; GET:i加1,然后输出Blackhox中第i小的数. 记住:第i小的数,就是Black Box里的数的按从小到大的顺序排序后的第i个元素.例如: 我们来演示一下一个有11个命令的命令串.(如下图所示)

洛谷 P1793 跑步_NOI导刊2010提高(04)

题目描述 新牛到部队, CG 要求它们每天早上搞晨跑,从A农场跑到B农场.从A农场到B农场中有n-2个路口,分别标上号,A农场为1号, B农场为n号,路口分别为 2 ..n -1 号,从A农场到B农场有很多条路径可以到达,而CG发现有的路口是必须经过的,即每条路径都经过的路口,CG要把它们记录下来,这样CG就可以先到那个路口,观察新牛们有没有偷懒,而你的任务就是找出所有必经路口. 输入输出格式 输入格式: 第一行两个用空格隔开的整数 n ( 3<=n<=2000 )和e ( 1<=e&l

【洛谷P1800】software_NOI导刊2010提高(06)

题目描述 一个软件开发公司同时要开发两个软件,并且要同时交付给用户,现在公司为了尽快完成这一任务,将每个软件划分成m个模块,由公司里的技术人员分工完成,每个技术人员完成同一软件的不同模块的所用的天数是相同的,并且是已知的,但完成不同软件的一个模块的时间是不同的,每个技术人员在同一时刻只能做一个模块,一个模块只能由一个人独立完成而不能由多人协同完成.一个技术人员在整个开发期内完成一个模块以后可以接着做任一软件的任一模块.写一个程序,求出公司最早能在什么时候交付软件. 输入输出格式 输入格式: 输入

洛谷 P1765 手机_NOI导刊2010普及(10) 题解

此文为博主原创题解,转载时请通知博主,并把原文链接放在正文醒目位置. 题目链接:https://www.luogu.org/problem/show?pid=1765 题目描述 一般的手机的键盘是这样的: 1 2 abc 3 def 4 ghi 5 jkl 6 mno 7 pqrs 8 tuv 9 wxyz * 0 # 要按出英文字母就必须要按数字键多下.例如要按出x就得按9两下,第一下会出w,而第二下会把w变成x.0键按一下会出一个空格. 你的任务是读取若干句只包含英文小写字母和空格的句子,求

洛谷 P1765 手机_NOI导刊2010普及(10)

题目描述 一般的手机的键盘是这样的: 1 2 abc 3 def 4 ghi 5 jkl 6 mno 7 pqrs 8 tuv 9 wxyz * 0 # 要按出英文字母就必须要按数字键多下.例如要按出x就得按9两下,第一下会出w,而第二下会把w变成x.0键按一下会出一个空格. 你的任务是读取若干句只包含英文小写字母和空格的句子,求出要在手机上打出这个句子至少需要按多少下键盘. 输入输出格式 输入格式: 一行一个句子,只包含英文小写字母和空格,且不超过200个字符. 输出格式: 一行一个整数,表示

洛谷—— P1765 手机_NOI导刊2010普及(10)

https://www.luogu.org/problem/show?pid=1765#sub 题目描述 一般的手机的键盘是这样的: 1 2 abc 3 def 4 ghi 5 jkl 6 mno 7 pqrs 8 tuv 9 wxyz * 0 # 要按出英文字母就必须要按数字键多下.例如要按出x就得按9两下,第一下会出w,而第二下会把w变成x.0键按一下会出一个空格. 你的任务是读取若干句只包含英文小写字母和空格的句子,求出要在手机上打出这个句子至少需要按多少下键盘. 输入输出格式 输入格式:

洛谷 P1767 家族_NOI导刊2010普及(10)

P1767 家族_NOI导刊2010普及(10) 题目描述 在一个与世隔绝的岛屿上,有一个有趣的现象:同一个家族的人家总是相邻的(这里的相邻是指东南西北四个方向),不同的家族之间总会有河流或是山丘隔绝,但同一个家族的人不一定有相同姓氏.现在给你岛上的地图,求出岛上有多少个不同的家族.岛上的地图有n行,每行有若干列,每个格子中要么是“ ”,表示大海,要么是“*”,表示河流或山丘,要么是小写字母,表示一户人家的姓氏. 输入输出格式 输入格式: 第一行是个数字N,表示下面信息的行数.接下来是N行字符,

洛谷——P1767 家族_NOI导刊2010普及(10)

P1767 家族_NOI导刊2010普及(10) 题目描述 在一个与世隔绝的岛屿上,有一个有趣的现象:同一个家族的人家总是相邻的(这里的相邻是指东南西北四个方向),不同的家族之间总会有河流或是山丘隔绝,但同一个家族的人不一定有相同姓氏.现在给你岛上的地图,求出岛上有多少个不同的家族.岛上的地图有n行,每行有若干列,每个格子中要么是“ ”,表示大海,要么是“*”,表示河流或山丘,要么是小写字母,表示一户人家的姓氏. 输入输出格式 输入格式: 第一行是个数字N,表示下面信息的行数.接下来是N行字符,