最大的一次收费最小,不由联想到二分
- 二分最大的一次收费mid,则要求从1走到n的路径上经过的点所收取的费用均不能超过mid
- 为了判断当前取mid能否走到终点,采用贪心的思想,应该走从1到n的最短路径(路径上的权值表示伤害,初始血量为b),即伤害最小
- 判断在伤害最小的路径上能否走到终点
const int N=10010;
vector<PII> g[N];
int cost[N];
int dist[N];
bool vis[N];
int n,m,b;
bool check(int mid)
{
memset(dist,0x3f,sizeof dist);
memset(vis,0,sizeof vis);
priority_queue<PII,vector<PII>,greater<PII> > heap;
dist[1]=0;
heap.push({0,1});
while(heap.size())
{
int t=heap.top().se;
heap.pop();
if(vis[t]) continue;
vis[t]=true;
for(int i=0;i<g[t].size();i++)
{
int j=g[t][i].fi,w=g[t][i].se;
if(cost[j]<=mid && dist[j]>dist[t]+w)
{
dist[j]=dist[t]+w;
heap.push({dist[j],j});
}
}
}
return dist[n]<=b;
}
int main()
{
cin>>n>>m>>b;
for(int i=1;i<=n;i++) cin>>cost[i];
int l=*min_element(cost+1,cost+n+1);
int r=*max_element(cost+1,cost+n+1);
while(m--)
{
int a,b,c;
cin>>a>>b>>c;
g[a].push_back({b,c});
g[b].push_back({a,c});
}
if(!check(INF))
{
puts("AFK");
return 0;
}
while(l<r)
{
int mid=l+r>>1;
if(check(mid)) r=mid;
else l=mid+1;
}
cout<<l<<endl;
//system("pause");
}