codevs 4175 洛谷 P1951 收费站(二分+spfa验证)
2016-11-11 14:23
239 查看
题目描述
在某个遥远的国家里,有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.
输入:
4 4 2 3 88
5
6
10
2 1 2
2 4 1
1 3 4
3 4 3
输出
8【数据规模】
对于60%的数据,满足n<=200,m<=10000,s<=200对于100%的数据,满足n<=10000,m<=50000,s<=1000000000
对于100%的数据,满足ci<=1000000000,fi<=1000000000,可能有两条边连接着相同的城市。
二分答案+spfa验证 但是会T一个点,所以可以用slf优化一下
#include<cstdio> #include<algorithm> #include<iostream> #include<cstring> #include<queue> using namespace std; const int SZ=150100; int n,m,u,v,s,maxn; int f[SZ]; struct edge { int f,t,d; }es[SZ<<1]; int tot=0,first[SZ<<1],nxt[SZ<<1]; void build(int f,int t,int d) { es[++tot]=(edge){f,t,d}; nxt[tot]=first[f]; first[f]=tot; } deque<int>q; bool vis[SZ]; int y[SZ]; int dis[SZ]; bool check(int x) { while(!q.empty()) q.pop_front(); for(int i=1;i<=n;i++) y[i]=1e9,vis[i]=0; y[u]=0; q.push_back(u); vis[u]=1; while(!q.empty()) { int ha=q.front(); q.pop_front(); vis[ha]=0; for(int i=first[ha];i;i=nxt[i]) { int gg=es[i].t; if(f[gg]<=x) {//cout<<y[gg]<<"---"<<endl; if(y[gg]>y[ha]+es[i].d) { y[gg]=y[ha]+es[i].d; if(gg==v&&y[gg]<=s) return true; if(!vis[gg]) { if(!q.empty()&&y[gg]<y[q.front()]) q.push_front(gg); else q.push_back(gg); vis[gg]=1; } } } } } return false; } queue<int>q2; bool vis2[SZ]; bool spfa() { vis2[u]=0; q2.push(u); while(!q2.empty()) { int gg=q2.front(); q2.pop(); for(int i=first[gg];i;i=nxt[i]) { int ha=es[i].t; if(ha==v) return true; if(!vis2[ha]) { vis2[ha]=1; q2.push(ha); } } } return false; } void read(int &a) { a=0;char c=getchar(); while(c<'0'||c>'9') c=getchar(); while(c>='0'&&c<='9') { a*=10;a+=c-'0'; c=getchar(); } } int main() { scanf("%d%d%d%d%d",&n,&m,&u,&v,&s); for(int i=1;i<=n;i++) read(f[i]),maxn=max(maxn,f[i]); for(int i=1;i<=m;i++) { int a,b,c; read(a);read(b);read(c); build(a,b,c); build(b,a,c); } if(spfa()) { int l=max(f[u],f[v]),r=maxn; while(l<=r) { int mid=(l+r)>>1; if(check(mid)) r=mid-1; else l=mid+1; } if(l>maxn) puts("-1"); else cout<<l; } else puts("-1"); return 0; }
相关文章推荐
- CODEVS 4175 收费站 二分+SPFA
- codevs 4175 收费站(二分+spfa)
- spfa进阶使用二分+SLF(洛谷1951 收费站_NOI导刊2009提高(2))
- codevs 4175 收费站(二分+SPFA)
- 洛谷1462 通往奥格瑞玛的道路 spfa+二分验证
- codevs 4175 二分+spfa判断
- <二分答案+spfa验证>codevs 1183 泥泞的道路
- 洛谷——P1951 收费站_NOI导刊2009提高(2)
- [codevs 1183][泥泞的道路(二分+spfa)
- 通往奥格瑞玛的道路_洛谷1462_二分+spfa
- 洛谷P1462 通往奥格瑞玛的道路 二分+spfa
- CodeVS1183 泥泞的道路 题解 【二分答案】【SPFA】
- 洛谷1462通往奥格瑞玛的道路(二分+spfa)
- 二分查找+spfa(洛谷1948 [USACO08JAN]电话线Telephone Lines) 4000
- BSOJ:2636 收费站--二分+SPFA(SLF优化)
- codevs 1183 泥泞的道路(二分答案+spfa验证)
- [洛谷1462 ]通往奥格瑞玛的道路---二分答案+spfa
- 洛谷1462 通往奥格瑞玛的道路 二分+spfa
- 洛谷2678 跳石头 二分验证
- 洛谷 P1608 路径统计 (spfa/Dij + 计数