題目
【題目背景】
由於小 X 是一位奆老, 奆老總是忙得一刻也停不下來。 他剛剛準備完食物, 小 X 童年的
摯友小 S 和小 Z 來找他幫忙了……
【題目描述】
小 S 和小 Z 十分喜歡看網絡寫手“” 的小說, 但由於需要付費才能閱讀, 而小 S 和小
Z 的零花錢有非常少, 他們只能找小 X 靠黑科技侵入給網站, 把小說給他們。
然而小 X 又非常的愛慕虛榮, 他要小 S 和小 Z 到自己家裏來取小說。
小 S、 小 Z 和小 X 都居住在揚中市, 揚中市共有 個小區, 條主幹道(假設每條主幹
道都是雙行線) 。 小 S 家住在 號小區, 小 X 家住在 號小區。 小 S 每經過一條主幹道需要
耗費 z 點體力, 但由於小 S 的人脈非常廣, 每當他到達一個小區, 他都會和好友攀談直到體
力回滿。
由於小 Z 也希望能看到小說, 所以他答應幫助小 S 次, 這 次小 S 經過主幹道不需要
耗費體力。
由於小 S 生性懶惰, 他希望耗費最少的體力到達小 X 家, 請問他最少耗費多少體力?
注意: 如果小 S 到小 X 家可以一路上都由小 Z 揹着, 那麼體力上限爲 ;
如果小 S 到不了小 X 家, 小 S 會很傷心, 體力上限爲;
【輸入格式】
第 1 行三個整數 , 意思如題目描述。
第 2 到第 n+1 行是 指走連接 號小區和 號小區的主幹道要耗費 點體力
【輸出格式】
一行一個整數, 表示小 S 最少耗費的體力。
【輸入樣例】
5 7 1
1 2 5
3 1 4
2 4 8
3 2 3
5 2 9
3 4 7
4 5 6
【輸出樣例】
4
【樣例解釋】
小 S 的行走路線:, 其中 這條主幹道由小 Z 幫助小 S 通過。
【數據範圍】
對於 30%的數據:
對於 60%的數據:
對於 100%的數據:
【後記】
附上兩句 的語錄:
1.扔掉一件東西的時候, 其實扔掉的不止是東西, 記下一件事情的時候, 其實記下的不止是
事情。
2.記在腦海裏的東西或許會被忘卻, 但記在心裏的東西, 是不會消逝的。
思路
這一題我過了(Day 2終於拿了一次第一 )
答案顯然具有單調性,所以可以進行二分答案。
於是,我們可以將問題轉化爲:有沒有一種方法,使體力上限不超過mid。
check函數很好寫,只需要把體力 > mid 的路徑看做1,把 < mid 的路徑看做0,dijkstra + 堆優化 即可(我也不知道要不要加優化,反正我加了)。
代碼
#include <bits/stdc++.h>
using namespace std;
const int M = 4010, N = 40100, Z = 1000000;
int n, m, k, dis[M], vis[M], s[M], t[N], e[N], l[N];
struct node {
int id, dis;
friend bool operator < (node a, node b) {return a.dis > b.dis;}
}; priority_queue <node> q;
int dijk(int x) {
memset(vis, 0, sizeof(vis));
memset(dis, 0x3f3f3f3f, sizeof(dis));
node f = (node){1, 0};
dis[1] = 0; q.push(f);
while (!q.empty()) {
f = q.top(); q.pop();
vis[f.id] = 1;
for (int i = s[f.id]; i != EOF; i = t[i]) {
int e2 = e[i], k2 = dis[f.id];
if (vis[e2]) continue;
if (l[i] >= x) k2++;
if (dis[e2] > k2) {
dis[e2] = k2;
node tmp = (node) {e2, dis[e2]};
q.push(tmp);
}
}
}
return dis[n] >= k+1;
}
int main() {
cin >> n >> m >> k;
memset(s, -1, sizeof(s));
int tot = 1, u, v, w;
for (int i = 1; i <= m; i++) {
cin >> u >> v >> w;
t[tot] = s[u], s[u] = tot, e[tot] = v, l[tot] = w, tot++;
t[tot] = s[v], s[v] = tot, e[tot] = u, l[tot] = w, tot++;
}
int l = 0, r = Z+100, ans = -1;
while (l <= r) {
int m = (l+r) >> 1;
if (dijk(m)) l = m+1, ans = m;
else r = m-1;
}
if (ans > Z) cout << -1 << endl;
else if (r < 0) cout << 0 << endl;
else cout << ans << endl;
return 0;
}