洛谷 P4408 [NOI2003] 逃学的小孩(树的直径)
[NOI2003] 逃學(xué)的小孩
題目描述
Chris 家的電話鈴響起了,里面?zhèn)鞒隽?Chris 的老師焦急的聲音:“喂,是 Chris 的家長(zhǎng)嗎?你們的孩子又沒(méi)來(lái)上課,不想?yún)⒓涌荚嚵藛?#xff1f;”一聽(tīng)說(shuō)要考試,Chris 的父母就心急如焚,他們決定在盡量短的時(shí)間內(nèi)找到 Chris。他們告訴 Chris 的老師:“根據(jù)以往的經(jīng)驗(yàn),Chris 現(xiàn)在必然躲在朋友 Shermie 或 Yashiro 家里偷玩《拳皇》游戲。現(xiàn)在,我們就從家出發(fā)去找 Chris,一但找到,我們立刻給您打電話。”說(shuō)完砰的一聲把電話掛了。
Chris 居住的城市由 NNN 個(gè)居住點(diǎn)和若干條連接居住點(diǎn)的雙向街道組成,經(jīng)過(guò)街道 xxx 需花費(fèi) TxT_{x}Tx? 分鐘。可以保證,任兩個(gè)居住點(diǎn)間有且僅有一條通路。Chris 家在點(diǎn) CCC,Shermie 和 Yashiro 分別住在點(diǎn) AAA 和點(diǎn) BBB。Chris 的老師和 Chris 的父母都有城市地圖,但 Chris 的父母知道點(diǎn) AAA、BBB、CCC 的具體位置而 Chris 的老師不知。
為了盡快找到 Chris,Chris 的父母會(huì)遵守以下兩條規(guī)則:
顯然,Chris 的老師知道 Chris 的父母在尋找 Chris 的過(guò)程中會(huì)遵守以上兩條規(guī)則,但由于他并不知道 AAA、BBB、CCC 的具體位置,所以現(xiàn)在他希望你告訴他,最壞情況下 Chris的父母要耗費(fèi)多長(zhǎng)時(shí)間才能找到 Chris?
輸入格式
輸入文件第一行是兩個(gè)整數(shù) NNN 和 MMM,分別表示居住點(diǎn)總數(shù)和街道總數(shù)。
以下 MMM 行,每行給出一條街道的信息。第 i+1i+1i+1 行包含整數(shù) UiU_{i}Ui?、ViV_{i}Vi?、TiT_{i}Ti?,表示街道 iii 連接居住點(diǎn) UiU_{i}Ui? 和 ViV_{i}Vi?,并且經(jīng)過(guò)街道 iii 需花費(fèi) TiT_{i}Ti? 分鐘。街道信息不會(huì)重復(fù)給出。
輸出格式
輸出文件僅包含整數(shù) TTT,即最壞情況下 Chris 的父母需要花費(fèi) TTT 分鐘才能找到 Chris。
樣例 #1
樣例輸入 #1
4 3 1 2 1 2 3 1 3 4 1樣例輸出 #1
4提示
對(duì)于 100%100\%100% 的數(shù)據(jù),3≤N≤2×1053 \le N \le 2\times 10^53≤N≤2×105,1≤Ui,Vi≤N1 \le U_{i},V_{i} \le N1≤Ui?,Vi?≤N,1≤Ti≤1091 \le T_{i} \le 10^{9}1≤Ti?≤109。
1、 兩次DFS 求樹(shù)的直徑隨便選擇一個(gè)點(diǎn)(假如是1), 求出所有點(diǎn)與1 的距離 d[k], 取一個(gè)點(diǎn)A ,使得d[A] 最大。那么A點(diǎn)一定是樹(shù)的直徑的一個(gè)端點(diǎn)。然后以A為頂點(diǎn),求出所有點(diǎn)與A的距離 d[k]( 1 <= k <= n), 取一個(gè)點(diǎn)B ,使得d[B] 最大.點(diǎn)A 和B之間的路徑一定是樹(shù)的直徑。 2、題目的答案就是 找到一個(gè)點(diǎn)k, 先從k點(diǎn)走到A點(diǎn),然后從A點(diǎn)走到B點(diǎn),距離 = dAK(或者dBK) + dAB; 總而言之,直徑dAB 是必須走的距離。 題目要求 k點(diǎn)走到 A 或者 B的距離取較小值,ans = max{dAB + min(dAk, dBk)} 3、 開(kāi)兩個(gè)距離數(shù)組 ll d1[N], d2[N];ll d1[N]; // A 點(diǎn)的距離數(shù)組ll d2[N]; // B 點(diǎn)的距離數(shù)組最后遍歷一下,取 max{ min(d1[k], d2[k])} 即可算法競(jìng)賽進(jìn)階指南,圖論習(xí)題 9
#include <bits/stdc++.h> using namespace std; typedef long long ll; const int N = 2e5 + 10, M = 4e5 + 10; int head[N], ver[M], Next[M], edge[M]; int n, m, tot; ll d1[N], d2[N]; int A, B; //樹(shù)的直徑的兩個(gè)端點(diǎn) bool vis[N]; ll maxlen; ll d0[N];void add(int x, int y, int z) {ver[++tot] = y, edge[tot] = z, Next[tot] = head[x], head[x] = tot; }void dfs(int x, ll d[]) {vis[x] = true;for(int i = head[x]; i; i = Next[i]){int y = ver[i];if(!vis[y]){d[y] = d[x] + edge[i]; dfs(y, d);}} }// ans = max{dAB + min(dAk, dBk)} void calc() {ll ans = 0; for(int i = 1; i <= n; ++i){if(i != A && i != B){// printf("d1[%d] = %d, d2[%d] = %d\n", i, d1[i], i, d2[i]);ll tmp = min(d1[i], d2[i]);ans = max(tmp, ans);}} // printf("d1[B] = %d\n", d1[B]);ans += d1[B];printf("%lld\n", ans); }int main() {scanf("%d%d", &n, &m);int x, y, z; for(int i = 0; i < m; ++i){scanf("%d%d%d", &x, &y, &z);add(x, y, z); add(y, x, z);}dfs(1, d0);for(int i = 1; i <= n; ++i){if(maxlen < d0[i]){maxlen = d0[i];A = i;}}memset(vis, false, sizeof vis);dfs(A, d1);maxlen = 0;for(int i = 1; i <= n; ++i){if(maxlen < d1[i]){maxlen = d1[i];B = i;}}memset(vis, false, sizeof vis);dfs(B, d2);//找到樹(shù)的直徑的兩個(gè)端點(diǎn) A, Bcalc();return 0; }總結(jié)
以上是生活随笔為你收集整理的洛谷 P4408 [NOI2003] 逃学的小孩(树的直径)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 大学计算机第一学期期末考试试题,《大学计
- 下一篇: Zhong__安装配置ElasticSe