题解:本题主要考察最短路+二分
简要题意:有
n
n
n个城市,
m
m
m条道路,通过城市
i
i
i需要
a
i
a_i
ai的钱,边有边权,先在给出限制
b
b
b,可以到达
n
n
n点且通过的边权不超过
b
b
b的情况下,经过的所有城市中最多的一次收取的费用的最小值是多少。
1.最短路+二分:首先语文要学好,我看了蛮久才明白题意,其实是要最小化经过点权的最大值!
知道后我们就可以二分了,二分通过城市钱的最大值,如果有一点的点权大于该值,就不通过。然后跑一边最短路,检测通过的边权之和是否大于
b
b
b:
1.如果大于,那么我们找到的最值就无效,继续向上二分,扩大范围。
2.如果小于,就向下二分,缩小范围
代码如下:
#include<iostream>
#include<algorithm>
#include<cstring>
#include<queue>
using namespace std;
struct E
{
int start,to,ans;
}e[666666];
int h[666666],a[666666],v[666666],d[666666];
int n,m,b,P;
void add(int start,int to,int ans)
{
e[++P].to=to;
e[P].ans=ans;
e[P].start=h[start];
h[start]=P;
}
bool spfa(int p,int w)
{
memset(v,0,sizeof(v));
memset(d,0x3f3f3f3f,sizeof(d));
queue<int> q;
q.push(p);
v[p]=1;d[p]=0;
while(!q.empty())
{
int t=q.front();
v[t]=0;q.pop();
for(int i=h[t];i;i=e[i].start)
{
int k=e[i].to;
if(d[t]+e[i].ans<d[k]&&a[k]<=w)
{
d[k]=d[t]+e[i].ans;
if(!v[k]){v[k]=1;q.push(k);}
}
}
}
if(d[n]<=b)return 1;
else return 0;
}
int main()
{
cin>>n>>m>>b;
for(int i=1;i<=n;i++)cin>>a[i];
for(int i=1;i<=m;i++)
{
int x,y,z;
cin>>x>>y>>z;
add(x,y,z);add(y,x,z);
}
if(spfa(1,1000000001)==0){cout<<"AFK";return 0;}
int l=1,r;
for(int i=1;i<=n;i++)r=max(r,a[i]);
while(l<=r)
{
int mid=l+r>>1;
if(spfa(1,mid)==1)r=mid-1;
else l=mid+1;
}
cout<<l<<endl;
return 0;
}