CODEVS 4175 收费站 二分+SPFA
2016-09-26 20:49
225 查看
题目描述 Description
在某个遥远的国家里,有n个城市。编号为1,2,3,……,n。
这个国家的政府修建了m条双向的公路。每条公路连接着两个城市。沿着某条公路,开车从一个城市到另一个城市,需要花费一定的汽油。
开车每经过一个城市,都会被收取一定的费用(包括起点和终点城市)。所有的收费站都在城市中,在城市间的公路上没有任何的收费站。
小红现在要开车从城市u到城市v(1<=u,v<=n)。她的车最多可以装下s升的汽油。在出发的时候,车的油箱是满的,并且她在路上不想加油。
在路上,每经过一个城市,她要交一定的费用。如果她某次交的费用比较多,她的心情就会变得很糟。所以她想知道,在她能到达目的地的前提下,她交的费用中最多的一次最少是多少。这个问题对于她来说太难了,于是她找到了聪明的你,你能帮帮她吗?
输入描述 Input Description
第一行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升汽油。
输出描述 Output Description
仅一个整数,表示小红交费最多的一次的最小值。
如果她无法到达城市v,输出-1。
数据范围及提示 Data Size & Hint
对于60%的数据,满足n<=200,m<=10000,s<=200
对于100%的数据,满足n<=10000,m<=50000,s<=1000000000
对于100%的数据,满足ci<=1000000000,fi<=1000000000,可能有两条边连接着相同的城市。
洛谷 P1462 通往奥格瑞玛的道路(和这个题简直一毛一样)
来填一个暑假里的旧坑…..
“如果她无法到达城市v,输出-1。”
从u开始跑最短路,如果dist[v]>S的话,就puts(“-1”);
重点是二分部分:
我在我的代码中用dq[i]表示每个城市的过路费,
l是min(dq[u],dq[v]),r是max dq[i],
对于每一个mid(在spfa里面是cost),跑一次spfa,如果当前点连接着的点的过路费dq[e.to]>cost,就直接略过这个点,跑完以后看dist[v],如果dist[v]>S,说明当前的mid(cost)太小,需要增大,如果dist[v]<=S,说明当前的mid太大,需要减小(如果dist[v]==S时,如果mid增大,解不会更优),当dist[v]<=S时,ans和mid取个min。
PS:SPFA一定要用双端优化…..(好像有个学长说过NOIP不会卡双端)
(后面有彩蛋)
BUT!
在洛谷交题,就死活T掉一个点。
还能再快点么?
答案是肯定的,我们在输入每个城市收的费用dq[i]时开一个数组hah[i]==dq[i],
然后hah小到大sort一遍,直接从hah里面二分,(这样最起码少了好几个常数,log(2) 10000≈13,log(2)1000000000≈30,由于spfa时间复杂度玄学,这样时间少了二分之一)
23333时间真的快了不少(在codevs上第一次交最后一个点卡800ms过的,优化后最后一个点只用了300多ms)
二分部分代码如下:
在某个遥远的国家里,有n个城市。编号为1,2,3,……,n。
这个国家的政府修建了m条双向的公路。每条公路连接着两个城市。沿着某条公路,开车从一个城市到另一个城市,需要花费一定的汽油。
开车每经过一个城市,都会被收取一定的费用(包括起点和终点城市)。所有的收费站都在城市中,在城市间的公路上没有任何的收费站。
小红现在要开车从城市u到城市v(1<=u,v<=n)。她的车最多可以装下s升的汽油。在出发的时候,车的油箱是满的,并且她在路上不想加油。
在路上,每经过一个城市,她要交一定的费用。如果她某次交的费用比较多,她的心情就会变得很糟。所以她想知道,在她能到达目的地的前提下,她交的费用中最多的一次最少是多少。这个问题对于她来说太难了,于是她找到了聪明的你,你能帮帮她吗?
输入描述 Input Description
第一行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升汽油。
输出描述 Output Description
仅一个整数,表示小红交费最多的一次的最小值。
如果她无法到达城市v,输出-1。
数据范围及提示 Data Size & Hint
对于60%的数据,满足n<=200,m<=10000,s<=200
对于100%的数据,满足n<=10000,m<=50000,s<=1000000000
对于100%的数据,满足ci<=1000000000,fi<=1000000000,可能有两条边连接着相同的城市。
洛谷 P1462 通往奥格瑞玛的道路(和这个题简直一毛一样)
来填一个暑假里的旧坑…..
“如果她无法到达城市v,输出-1。”
从u开始跑最短路,如果dist[v]>S的话,就puts(“-1”);
重点是二分部分:
我在我的代码中用dq[i]表示每个城市的过路费,
l是min(dq[u],dq[v]),r是max dq[i],
对于每一个mid(在spfa里面是cost),跑一次spfa,如果当前点连接着的点的过路费dq[e.to]>cost,就直接略过这个点,跑完以后看dist[v],如果dist[v]>S,说明当前的mid(cost)太小,需要增大,如果dist[v]<=S,说明当前的mid太大,需要减小(如果dist[v]==S时,如果mid增大,解不会更优),当dist[v]<=S时,ans和mid取个min。
PS:SPFA一定要用双端优化…..(好像有个学长说过NOIP不会卡双端)
(后面有彩蛋)
/* 本题中使用的时间优化: 1、读入优化 2、双端队列spfa优化 */ #include<cstdio> #include<algorithm> #include<cmath> #include<iostream> #include<cstring> #include<queue> using namespace std; typedef long long ll; const int maxn=200000+500; const ll inf=20000000000000000ll; struct Edge { int f; int to; ll d; int next; }edge[maxn]; int n,m,u,v; int dq[maxn]; int head[maxn]; bool vis[maxn]; ll dist[maxn]; ll S; int mincost; int maxcost; int tot; void add(int f,int t,int d) { edge[++tot].f=f; edge[tot].to=t; edge[tot].d=d; edge[tot].next=head[f]; head[f]=tot; } deque<int>q; void clr() { memset(vis,0,sizeof(vis)); for(int i=1;i<=n;i++) dist[i]=inf; } bool spfa1() { clr(); q.push_front(u); dist[u]=0; while(!q.empty()) { int x=q.front(); vis[x]=0; q.pop_front(); for(int i=head[x];i;i=edge[i].next) { Edge e=edge[i]; if(dist[e.to]>dist[x]+e.d) { dist[e.to]=dist[x]+e.d; if(!vis[e.to]) { vis[e.to]=1; if(!q.empty()) { if(dist[e.to]<dist[q.front()]) q.push_front(e.to); else q.push_back(e.to); } else q.push_back(e.to); } } } } if(dist[v]>S) return false; return true; } ll maxway=inf; bool spfa(int cost) { if(dq[u] > cost || dq[v] > cost) return 0; clr(); q.push_front(u); dist[u]=0; while(!q.empty()) { int x=q.front(); vis[x]=0; q.pop_front(); for(int i=head[x];i;i=edge[i].next) { Edge e=edge[i]; if(dq[e.to]>cost) continue; else { if(dist[e.to]>dist[x]+e.d) { dist[e.to]=dist[x]+e.d; if(!vis[e.to]) { if(!q.empty()) { if(dist[e.to]<dist[q.front()]) q.push_front(e.to); else q.push_back(e.to); } else q.push_back(e.to); vis[e.to]=1; } } } } } ll hah=dist[v]; if(hah>S) { return true; }//到不了了,缴费需增大 else if(hah<=S)//能到 { return false; } } // 缴费↑,能走的城市↑,dist v↓, // 缴费↓,能走的城市↓,dist v↑, int div() { int ans=maxcost; int l=mincost; int r=maxcost; while(l<=r) { int mid=(l+r)>>1; if(spfa(mid)) { l=mid+1; } else { ans=min(ans,mid);//不能到你更新个鬼咯 r=mid-1; } // printf("l:%d r:%d mid:%d\n",l,r,mid); } return ans; } int read(int &a) { char c=getchar(); while(c>'9'||c<'0') { c=getchar(); } int ans=0; while(c>='0'&&c<='9') { ans=(ans<<3)+(ans<<1); ans+=c-'0'; c=getchar(); } a=ans; return a; } ll readl(ll &a) { char c=getchar(); while(c>'9'||c<'0') { c=getchar(); } ll ans=0; while(c>='0'&&c<='9') { ans=(ans<<3)+(ans<<1); ans+=(ll)(c-'0'); c=getchar(); } a=ans; return a; } int main() { freopen("cost.in","r",stdin); freopen("cost.out","w",stdout); read(n),read(m),read(u),read(v),readl(S); for(int i=1;i<=n;i++) read(dq[i]),maxcost=max(maxcost,dq[i]); for(int i=1;i<=m;i++) { int a,b; ll c; read(a),read(b),readl(c); add(a,b,c); add(b,a,c); } mincost=max(dq[u],dq[v]); if(!spfa1()) puts("-1"); else printf("%d",div()); return 0; }
BUT!
在洛谷交题,就死活T掉一个点。
还能再快点么?
答案是肯定的,我们在输入每个城市收的费用dq[i]时开一个数组hah[i]==dq[i],
然后hah小到大sort一遍,直接从hah里面二分,(这样最起码少了好几个常数,log(2) 10000≈13,log(2)1000000000≈30,由于spfa时间复杂度玄学,这样时间少了二分之一)
23333时间真的快了不少(在codevs上第一次交最后一个点卡800ms过的,优化后最后一个点只用了300多ms)
二分部分代码如下:
int div() { int ans=n; int l=1; int r=n; while(l<=r) { int mid=(l+r)>>1; if(spfa(hah[mid])) { l=mid+1; } else { ans=min(ans,mid); r=mid-1; } // printf("l:%d r:%d mid:%d\n",l,r,mid); } return hah[ans]; }
相关文章推荐
- codevs 4175 洛谷 P1951 收费站(二分+spfa验证)
- codevs 4175 二分+spfa判断
- codevs 4175 收费站(二分+SPFA)
- codevs 4175 收费站(二分+spfa)
- spfa进阶使用二分+SLF(洛谷1951 收费站_NOI导刊2009提高(2))
- [codevs 1183][泥泞的道路(二分+spfa)
- CodeVS1183 泥泞的道路 题解 【二分答案】【SPFA】
- BSOJ:2636 收费站--二分+SPFA(SLF优化)
- 洛谷P1462 通往奥格瑞玛的道路 二分+spfa
- hdu 1839 Delay Constrained Maximum Capacity Path 二分下限+最短路spfa
- bzoj 1614: [Usaco2007 Jan]Telephone Lines架设电话线(二分+SPFA)
- 洛谷1462 通往奥格瑞玛的道路 二分+spfa
- POJ 3662 Telephone Lines 电话线(二分答案+SPFA)
- hdu 1839 Delay Constrained Maximum Capacity Path(spfa+二分)
- 01参数搜索+二分+spfa判负环
- 【二分答案+spfa】架设电话线
- <二分答案+spfa验证>codevs 1183 泥泞的道路
- 复赛模拟试题 - 收费站 Dijkstra迪杰斯特拉+二分答案法 重庆一中高2018级竞赛班第九次测试 2016.9.10 Problem 4
- 关于二分答案的图论问题(spfa)
- UVALive 4223 Trucking 二分+spfa