二次联通门 : luogu P1462 通往奥格瑞玛的道路
/* luogu P1462 通往奥格瑞玛的道路 二分答案 + 最短路 二分最大钱数 每次只走小于当前钱数的路 若最后的血量可以 则证明答案可行 就继续二分 */ #include <iostream> #include <cstring> #include <cstdio> #include <queue> #define Max 10005 #define INF 1e7 using namespace std; inline int max (int a, int b) { return a > b ? a : b; } inline int min (int a, int b) { return a < b ? a : b; } void read (int &now) { now = 0; char word = getchar (); while (word > '9' || word < '0') word = getchar (); while (word >= '0' && word <= '9') { now = now * 10 + word - '0'; word = getchar (); } } struct Edge { int to; int dis; int next; }edge[Max * 10]; int edge_list[Max]; int Edge_Count; int dis[Max]; int N, M; bool visit[Max]; int cost[Max]; int Blood; inline void AddEdge (int from, int to, int dis) { Edge_Count++; edge[Edge_Count].to = to; edge[Edge_Count].dis = dis; edge[Edge_Count].next = edge_list[from]; edge_list[from] = Edge_Count; } bool Check (int Money) { if (Money < cost[1]) return false; queue <int> Queue; for (int i = 1; i <= N + 5; i++) { visit[i] = false; dis[i] = INF; } visit[1] = true; dis[1] = 0; Queue.push (1); int now; while (!Queue.empty()) { now = Queue.front (); Queue.pop (); visit[now] = false; for (int i = edge_list[now]; i; i = edge[i].next) if (cost[edge[i].to] <= Money && dis[edge[i].to] > edge[i].dis + dis[now]) { dis[edge[i].to] = edge[i].dis + dis[now]; if (!visit[edge[i].to]) { Queue.push (edge[i].to); visit[edge[i].to] = true; } } } if (dis[N] <= Blood) return true; else return false; } int main (int argc, char *argv[]) { read (N); read (M); read (Blood); int l = INF, r = 0; for (int i = 1; i <= N; i++) { read (cost[i]); l = min (l, cost[i]); r = max (r, cost[i]); } int u, v, x; for (int i = 1; i <= M; i++) { read (u); read (v); read (x); AddEdge (u, v, x); AddEdge (v, u, x); } int Mid; int Answer; while (l <= r) { Mid = (l + r) >> 1; if (Check (Mid)) { r = Mid - 1; Answer = Mid; } else l = Mid + 1; } if (Answer) printf ("%d", Answer); else printf ("AFK"); return 0; }