题目描述
在某个遥远的国家里,有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.
输入输出样例
说明
【数据规模】
对于60%的数据,满足n<=200,m<=10000,s<=200
对于100%的数据,满足n<=10000,m<=50000,s<=1000000000
对于100%的数据,满足ci<=1000000000,fi<=1000000000,可能有两条边连接着相同的城市。
My:二分答案+spfa
A:4 T:3 WA:3
正解:如上,但是少判断了一个细节(如果起点的f[]值>mid,这也是不合法的),导致WA:3
交费最多的一次最小,典型的二分
假设二分值mid为当前最大值,
判定:那么 f[i]>mid 的城市在当前状态下不可到达
如果此时到T的油花费<=oil 即为可行。
但是不能忍的是他居然卡spfa,还要加spfa的优化
还有,记得开long long
1 #include<iostream> 2 #include<cstdio> 3 #include<algorithm> 4 #include<cmath> 5 #include<cstring> 6 #include<string> 7 #include<queue> 8 #define ll long long 9 #define inf 2147483600 10 using namespace std; 11 const int N=1e7+10; 12 struct node{ 13 int u,v,c,ne; 14 }e[N]; 15 int n,m,S,T,tot,h[N],oil; 16 int f[N],L,R; 17 void add(int u,int v,int c) 18 { 19 tot++;e[tot]=(node){u,v,c,h[u]};h[u]=tot; 20 } 21 deque<int>q; 22 ll d[N]; 23 bool v[N]; 24 bool ok(int x) 25 { 26 for(int i=1;i<=n;++i) d[i]=inf,v[i]=0; 27 if(f[S]>x) return 0; 28 q.push_back(S);d[S]=0;v[S]=1; 29 while(!q.empty()) 30 { 31 int ff=q.front();q.pop_front();v[ff]=0; 32 if(d[ff]>oil) continue; 33 for(int i=h[ff];i;i=e[i].ne) 34 { 35 int rr=e[i].v; 36 if(f[rr]>x) continue; 37 if(d[rr]>d[ff]+e[i].c) 38 { 39 d[rr]=d[ff]+e[i].c; 40 if(!v[rr]) 41 { 42 v[rr]=1; 43 if(q.empty() || d[rr]>=d[q.front()]) q.push_back(rr); 44 else q.push_front(rr); 45 } 46 } 47 } 48 } 49 return d[T]<=(ll)oil; 50 } 51 int main() 52 { 53 scanf("%d%d%d%d%d",&n,&m,&S,&T,&oil); 54 L=1e9+2;R=-1e9-3; 55 for(int i=1;i<=n;++i) 56 { 57 scanf("%d",&f[i]); 58 L=min(f[i],L); 59 R=max(R,f[i]); 60 } 61 for(int i=1;i<=m;++i) 62 { 63 int x,y,z;scanf("%d%d%d",&x,&y,&z); 64 add(x,y,z);add(y,x,z); 65 } 66 int ans=-1; 67 while(L<=R) 68 { 69 int mid=(L+R)>>1; 70 if(ok(mid)) R=mid-1,ans=mid; 71 else L=mid+1; 72 } 73 printf("%d",ans); 74 return 0; 75 }
攻人之恶毋太严,要思其堪受;教人之善毋太高,当使其可从。