在艾澤拉斯大陸上有一位名叫歪嘴哦的神奇術士,他是部落的中堅力量node
有一天他醒來後發現本身竟然到了聯盟的主城暴風城ios
在被衆多聯盟的士兵攻擊後,他決定逃回本身的家鄉奧格瑞瑪spa
在艾澤拉斯,有n個城市。編號爲1,2,3,...,n。code
城市之間有m條雙向的公路,鏈接着兩個城市,從某個城市到另外一個城市,會遭到聯盟的攻擊,進而損失必定的血量。ci
每次通過一個城市,都會被收取必定的過路費(包括起點和終點)。路上並無收費站。get
假設1爲暴風城,n爲奧格瑞瑪,而他的血量最多爲b,出發時他的血量是滿的。string
歪嘴哦不但願花不少錢,他想知道,在能夠到達奧格瑞瑪的狀況下,他所通過的全部城市中最多的一次收取的費用的最小值是多少。it
第一行3個正整數,n,m,b。分別表示有n個城市,m條公路,歪嘴哦的血量爲b。io
接下來有n行,每行1個正整數,fi。表示通過城市i,須要交費fi元。class
再接下來有m行,每行3個正整數,ai,bi,ci(1<=ai,bi<=n)。表示城市ai和城市bi之間有一條公路,若是從城市ai到城市bi,或者從城市bi到城市ai,會損失ci的血量。
僅一個整數,表示歪嘴哦交費最多的一次的最小值。
若是他沒法到達奧格瑞瑪,輸出AFK。
輸入 #1
4 4 8
8
5
6
10
2 1 2
2 4 1
1 3 4
3 4 3
輸出 #1
10
對於60%的數據,知足n≤200,m≤10000,b≤200
對於100%的數據,知足n≤10000,m≤50000,b≤1000000000
對於100%的數據,知足ci≤1000000000,fi≤1000000000,可能有兩條邊鏈接着相同的城市。
最短路 + dijkstra + 二分答案
走每一條路都會消耗必定的血量
到每個城市都會話費必定的金錢
求在活着的狀況下通過的城市中交的金錢最多的最少
使最多的最少
很顯然在提示你要用二分答案
二分有兩個選擇:
1.二分血量
2.二分花費最多的城市花的錢
若是二分血量
那處理起來就至關麻煩了
可是若是二分花費
限制了哪些城市不能走
這樣就能夠check在限制以外的城市中能不能活着到達目的地
看活着的狀況
通過的路徑血量消耗不等大於等於歪嘴哦的血量
注意:
即便是等於也是不行的
這樣的話在二分的前提之下(只走花費不超過二分值的城市)
要讓消耗的血量最少
並且消耗的血量是依附於某條路徑的
因此能夠當成路徑的權值來跑
二分花費最高城市的花費
而後跑dijkstra
由於有了最高花費的限制
因此花費超出二分值的城市就不可以被進行鬆弛操做
用剩下的跑一下最短路
看看最後1-n的最少消耗的血量是否是小於歪嘴哦的血量
若是小於那就返回真
反之返回假
#include<iostream> #include<cstdio> #include<cstring> #include<queue> #define int long long using namespace std; int read() { int sum = 0,fg = 1; char c = getchar(); while(c < '0' || c > '9') { if(c == '-')fg = -1; c = getchar(); } while(c >= '0' && c <= '9') { sum = sum * 10 + c - '0'; c = getchar(); } return sum * fg; } const int Max = 10004; int f[Max]; struct node { int y,ne; int z; }a[Max * 10]; int head[Max],sum = 0; void add(int x,int y,int z) { a[++ sum].y = y; a[sum].ne = head[x]; a[sum].z = z; head[x] = sum; } struct point { int x; int w; bool operator < (const point xx) const { return xx.w < w; } }; int dis[Max]; bool use[Max]; priority_queue<point>q; int n,m,hp; bool check(int mid) { memset(dis,0x3f,sizeof(dis)); memset(use,false,sizeof(use)); dis[1] = 0; q.push((point){1,0}); while(!q.empty()) { int x = q.top().x; q.pop(); if(use[x] == true) continue; use[x] = true; for(register int i = head[x];i != 0;i = a[i].ne) { int awa = a[i].y; if(dis[awa] > dis[x] + a[i].z && f[awa] <= mid) { dis[awa] = dis[x] + a[i].z; if(use[awa] == false) q.push((point){awa,dis[awa]}); } } } if(dis[n] < hp) return true; return false; } signed main() { n = read(),m = read(),hp = read(); int r = 0; for(register int i = 1;i <= n;++ i) f[i] = read(),r = max(r,f[i]); for(register int i = 1;i <= m;++ i) { int x = read(),y = read(),z = read(); add(x,y,z); add(y,x,z); } int qwq = r; r ++; int l = 0; while(l < r) { int mid = (r + l) >> 1; if(check(mid))r = mid; else l = mid + 1; } if(l == qwq + 1) { cout << "AFK" << endl; return 0; } cout << l << endl; return 0; }