日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

【洛谷】【二分答案+最短路】P1462 通往奥格瑞玛的道路

發布時間:2023/12/1 编程问答 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【洛谷】【二分答案+最短路】P1462 通往奥格瑞玛的道路 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
在艾澤拉斯大陸上有一位名叫歪嘴哦的神奇術士,他是部落的中堅力量有一天他醒來后發現自己居然到了聯盟的主城暴風城在被眾多聯盟的士兵攻擊后,他決定逃回自己的家鄉奧格瑞瑪 題目背景

【題目描述:】

在艾澤拉斯,有n個城市。編號為1,2,3,...,n。

城市之間有m條雙向的公路,連接著兩個城市,從某個城市到另一個城市,會遭到聯盟的攻擊,進而損失一定的血量。

每次經過一個城市,都會被收取一定的過路費(包括起點和終點)。路上并沒有收費站。

假設1為暴風城,n為奧格瑞瑪,而他的血量最多為b,出發時他的血量是滿的。

歪嘴哦不希望花很多錢,他想知道,在可以到達奧格瑞瑪的情況下,他所經過的所有城市中最多的一次收取的費用的最小值是多少。

【輸入格式:】

第一行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的血量。

【輸出格式:】

僅一個整數,表示歪嘴哦交費最多的一次的最小值。

如果他無法到達奧格瑞瑪,輸出AFK。

輸入樣例#14 4 8 8 5 6 10 2 1 2 2 4 1 1 3 4 3 4 3 輸出樣例#110 輸入輸出樣例

?

【算法分析:】

問題可以看作:

給定一張圖,給定邊權和點權,給定一個最大邊權,

問,從點1到點n的路徑的總長度不大于最大邊權時點權的最大值最小

假設一個最大值,問題就變成了

  求出一條經過的點的點權都不大于這個最大值的最短路徑,并且這條最短路的長度小于最大邊權(生命值為0就GG了)

?

好像可以二分答案,證一證它的單調性:

當一個數num被選為最大值的時候,如果存在一條“經過的點的點權都不大于這個最大值的最短路徑,并且這條最短路的長度小于最大邊權”

則num可以選為最大值。

當num變小時,可以經過的城市變少,可選的點數變少,受到的傷害便可能增多,

使受到的傷害盡可能大(但不能超過總生命值),最大的點權值就會盡可能小,

  故num不一定是最優解,所以從[l, mid]內尋找解

  當num作為最大值過小時,就要從[mid + 1, r]中尋找解.

?

也就是說這道題將傷害視作邊權,二分點權最大值,跑最短路松弛的條件多加了一個:松弛的點的點權必須小于最大點權

每次跑完最短路后如果受到的傷害小于血量那么這個最大點權便是一個解.

?

【代碼:】

1 //通往奧格瑞瑪的道路 2 #include<iostream> 3 #include<cstdio> 4 #include<cstring> 5 using namespace std; 6 7 const int MAXN = 10000 + 1; 8 const int MAXM = 50000 + 1; 9 const int INF = 0x3f3f3f3f; 10 11 int n, m, blood; 12 int city[MAXN]; 13 14 int edge_num, head[MAXN]; 15 struct edge { 16 int len, to, next; 17 }h[MAXM * 2]; 18 19 inline void Add(int from, int to, int len) { 20 h[++edge_num].next = head[from]; 21 h[edge_num].to = to, h[edge_num].len = len; 22 head[from] = edge_num; 23 } 24 25 inline int read() { 26 int x = 0; char ch = getchar(); 27 while(ch < '0' || ch > '9') ch = getchar(); 28 while(ch >= '0' && ch <= '9') 29 x = (x << 3) + (x << 1) + ch - 48, ch = getchar(); 30 return x; 31 } 32 33 int fro, rear; 34 int dis[MAXN], que[MAXN * 20]; 35 bool in_que[MAXN]; 36 void SPFA(int money) { 37 for(int i = 0; i <= n; i++) dis[i] = INF; 38 memset(in_que, 0, sizeof(in_que)); 39 in_que[1] = 1, dis[1] = 0; 40 que[fro = rear = 1] = 1; 41 while(fro <= rear) { 42 int x = que[fro++]; 43 in_que[x] = 0; 44 for(int i = head[x]; i; i = h[i].next) { 45 int l = h[i].len, y = h[i].to; 46 if(dis[x] + l < dis[y] && city[y] <= money) { 47 dis[y] = dis[x] + l; 48 if(!in_que[y]) in_que[y] = 1, que[++rear] =y; 49 } 50 } 51 } 52 } 53 54 inline bool check(int money) { 55 SPFA(money); 56 return dis[n] < blood; 57 } 58 int main() { 59 int l = 0, r = 0; 60 n = read(), m = read(), blood = read(); 61 for(int i = 1; i <= n; ++i) { 62 city[i] = read(); 63 r = max(r, city[i]); 64 } 65 l = max(city[1], city[n]); 66 for(int i = 1; i <= m; ++i) { 67 int a, b, c; 68 a = read(), b = read(), c = read(); 69 if(a != b) { 70 Add(a, b, c); 71 Add(b, a, c); 72 } 73 } 74 if(!check(r)) { puts("AFK"); return 0; } 75 while(l <= r) { 76 int mid = (l + r) >> 1; 77 if(!check(mid)) l = mid + 1; 78 else r = mid - 1; 79 } 80 printf("%d\n", l); 81 }

?

轉載于:https://www.cnblogs.com/devilk-sjj/p/9042030.html

總結

以上是生活随笔為你收集整理的【洛谷】【二分答案+最短路】P1462 通往奥格瑞玛的道路的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。