本題的描述仍是很清晰的,徹底能夠直接傳送門去看node
可是惟一想要強調的是:初看本題可能會像我同樣認爲是點權+邊權處理而後直接跑最短路...然鵝並非這樣c++
我覺得的點權實際上是通過該城市的費用,是最終的答案算法
我覺得的邊權實際上是通過該條邊的流血量,是用來判斷某一條從\(1\)到\(N\)的路徑是否合法數組
什麼意思?函數
就是要求咱們找到一條路,知足:spa
這條路上全部的流血量之和必須<\(b\)(給定的初始血量).net
這條路上通過的全部城市中最大費用值最小code
又是至關於同時維護兩個東西,難搞htm
在以前有些題 中,咱們會選擇「枚舉其中一個再求解另一個的思路」
答案是確定的,可是面對這道題的數據範圍:\(ci≤1000000000,fi≤1000000000\)
對了,那就是二分答案
咱們二分最大費用值最小,而後去\(check\)一下當前二分的答案是否合法:便是否有路徑可以從\(1\)到\(N\)且路徑上城市花費值≤當前的答案
咱們能夠開另一個數組\(C'\)代替原來的城市費用數組\(C\)啊!而後直接對\(C'\)進行\(sort\),那咱們就能夠對\(C'\)這個有序數列進行二分了!
sort(cc+1,cc+1+n); //變成有序序列 ans=cc[n]; l=1;r=n; while(l<=r) { //注意一下這裏二分的是下標並非直接的值 long long mid=(l+r)>>1; if(check(cc[mid])==true) { ans=cc[mid]; r=mid-1; } else l=mid+1; } printf("%lld",ans);
inline bool check(long long x) { for(register int i=1;i<=n;i++) flag[i]=0; //記得清空! for(register int i=1;i<=n;i++) { if(c[i]>x) flag[i]=1; //全部大於當前答案的城市都不能走 } dijkstra(); if(dis[n]==1000000000+1||dis[n]>=b) return false; return true; }
#include <bits/stdc++.h> using namespace std; long long b,w,r,ans,l,c[5100005],cc[5100005]; int n,m,u,v,tot,dis[5100005],vis[5100005],flag[5100005]; int head[5100005]; priority_queue<pair<int,int> > shan; struct node { int to,net; long long val; } e[5100005]; inline void add(int u,int v,int w) { e[++tot].to=v; e[tot].val=w; e[tot].net=head[u]; head[u]=tot; } inline void dijkstra() { for(register int i=1;i<=n;i++) { vis[i]=0; dis[i]=1000000000+1; } dis[1]=0; shan.push(make_pair(0,1)); while(!shan.empty()) { int x=shan.top().second; shan.pop(); if(vis[x]) continue; vis[x]=1; for(register int i=head[x];i;i=e[i].net) { int v=e[i].to; if(dis[v]>dis[x]+e[i].val&&flag[x]==0&&flag[v]==0) { dis[v]=dis[x]+e[i].val; shan.push(make_pair(-dis[v],v)); } } } } inline bool check(long long x) { for(register int i=1;i<=n;i++) flag[i]=0; for(register int i=1;i<=n;i++) { if(c[i]>x) flag[i]=1; } dijkstra(); if(dis[n]==1000000000+1||dis[n]>=b) return false; return true; } int main() { scanf("%d%d%lld",&n,&m,&b); for(register int i=1;i<=n;i++) { scanf("%lld",&c[i]); cc[i]=c[i]; } for(register int i=1;i<=m;i++) { scanf("%d%d%lld",&u,&v,&w); add(u,v,w); add(v,u,w); } dijkstra(); if(dis[n]==1000000000+1||dis[n]>=b) { puts("AFK"); return 0; } sort(cc+1,cc+1+n); ans=cc[n]; l=1;r=n; while(l<=r) { long long mid=(l+r)>>1; if(check(cc[mid])==true) { ans=cc[mid]; r=mid-1; } else l=mid+1; } printf("%lld",ans); return 0; }