您的位置:首页 > 其它

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 8

8

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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: