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 }