洛谷 P1462 通往奧格瑞瑪的道路
Description
在艾澤拉斯大陸上有一位名叫歪嘴哦的神奇術士,他是部落的中堅力量
有一天他醒來後發現自己居然到了聯盟的主城暴風城
在被眾多聯盟的士兵攻擊後,他決定逃回自己的家鄉奧格瑞瑪
在艾澤拉斯,有n個城市。編號為1,2,3,...,n。
城市之間有m條雙向的公路,連接著兩個城市,從某個城市到另一個城市,會遭到聯盟的攻擊,進而損失一定的血量。
每次經過一個城市,都會被收取一定的過路費(包括起點和終點)。路上並沒有收費站。
假設1為暴風城,n為奧格瑞瑪,而他的血量最多為b,出發時他的血量是滿的。
歪嘴哦不希望花很多錢,他想知道,在可以到達奧格瑞瑪的情況下,他所經過的所有城市中最多的一次收取的費用的最小值是多少。
Input
第一行3個正整數,n,m,b。分別表示有n個城市,m條公路,歪嘴哦的血量為b。
接下來有n行,每行1個正整數,fi。表示經過城市i,需要交費fi元。
再接下來有m行,每行3個正整數,ai,bi,ci(1<=ai,bi<=n)。表示城市ai和城市bi之間有一條公路,如果從城市ai到城市bi,或者從城市bi到城市ai,會損失ci的血量。
Output
僅一個整數,表示歪嘴哦交費最多的一次的最小值。
如果他無法到達奧格瑞瑪,輸出AFK。
Sample Input
4 4 8
8
5
6
10
2 1 2
2 4 1
1 3 4
3 4 3
Sample Output
10
Hint
對於60%的數據,滿足n≤200,m≤10000,b≤200
對於100%的數據,滿足n≤10000,m≤50000,b≤1000000000
對於100%的數據,滿足ci≤1000000000,fi≤1000000000,可能有兩條邊連接著相同的城市。
思路顯然:二分 + 最短路,註意數據範圍(被long long坑了...dis數組會爆);
代碼:
1 /* 2 二分 + 最短路 3 */ 4 #include<iostream> 5 #include<cstdio> 6 #include<cstring> 7#include<queue> 8 typedef long long ll; 9 10 const int maxn = 10000 + 5; 11 const int maxm = 50000 + 5;//雙向 12 struct Edge 13 { 14 int f, t, v; 15 }gra[maxm << 1]; 16 int n, m, heal, u, arr[maxn]; 17 int fir[maxn], nxt[maxm << 1]; 18 ll dis[maxn]; 19 bool used[maxn]; 20 std::queue<int>Q; 21 void Build(int, int, int); 22 bool Check(int); 23 24 int main() 25 { 26 memset(fir, -1, sizeof(fir)); 27 scanf("%d%d%d", &n, &m, &heal); 28 int l = 1e9 + 7, r = -1; 29 for(int i = 1; i <= n; i++) 30 scanf("%d", &arr[i]), 31 l = std::min(l, arr[i]), r = std::max(r, arr[i]); 32 for(int i = 1; i <= m; i++) 33 { 34 int f, t, v; 35 scanf("%d%d%d", &f, &t, &v); 36 Build(f, t, v); 37 } 38 bool f = 0; 39 while(l <= r) 40 { 41 int mid = l + r >> 1; 42 if(Check(mid)) r = mid - 1, f = 1; 43 else l = mid + 1; 44 } 45 if(!f) puts("AFK"); 46 else std::cout << r + 1; 47 return 0; 48 } 49 50 bool Check(int ans) 51 { 52 if(arr[1] > ans||arr[n] > ans) return 0; 53 memset(dis, 0x7f, sizeof(dis)); 54 dis[1] = 0; 55 Q.push(1); 56 while(!Q.empty()) 57 { 58 int k = Q.front(); 59 Q.pop(); 60 used[k] = 0; 61 for(int i = fir[k]; ~i; i = nxt[i]) 62 { 63 int tmp = gra[i].t; 64 if(arr[tmp] > ans) continue; 65 if(dis[tmp] > dis[k] + (ll)gra[i].v) 66 { 67 dis[tmp] = dis[k] + (ll)gra[i].v; 68 if(used[tmp]) continue; 69 used[tmp] = 1; 70 Q.push(tmp); 71 } 72 } 73 } 74 if(dis[n] >= (ll)heal) return 0; 75 return 1; 76 } 77 78 void Build(int f, int t, int v) 79 { 80 gra[++u] = (Edge){f, t, v}; 81 nxt[u] = fir[f], fir[f] = u; 82 gra[++u] = (Edge){t, f, v}; 83 nxt[u] = fir[t], fir[t] = u; 84 }
洛谷 P1462 通往奧格瑞瑪的道路