手玩樣例,我們很快(從題目後的提示)找到了 1−3
1 - 3
1−3, 1−2
−31-2-3
1−2−3,1−2
−31 - 2 - 3
1−2−
3(兩者不同)一共三條路徑。求出其權值之和再加上乘船返回兩次所需的時間,和樣例恰好一致。
於是我們便可以把這個問題分成兩個子問題逐個求解:
選擇從起點開始dfs
,我們需要考慮在搜尋樹上,我們怎樣進行狀態與狀態之間的轉移(說白了就是dfs
函式裡寫什麼)。
我們對症下藥:題目讓求起點到終點路徑的權值和,我們就先存下起點到當前點路徑的權值和,用s
陣列儲存;題目讓求起點到終點路徑的數目,我們就先存下起點到當前點路徑的數目,用cnt
陣列儲存。
搜尋樹上,父親想要告訴兒子什麼呢?肯定就是s[fa]
和cnt[fa]
的數值了。那麼作為父親最喜愛的兒子(誤),怎樣處理好父親給的資訊呢?我們具體分析。
假設我們當前節點(父親)為2
,即將處理的邊為 權值為 $ 7 $ 的邊,那麼兒子節點就是3
。 我們發現有了這條邊之後,1 -> 2
的每一條路徑都可以和它組合,成為1 -> 3
的一條新路徑。
因此這條邊對於權值之和的貢獻是:通過1 -> 2
的每一條不相同的路和這條邊的權值總和。這條邊對於路徑數量的貢獻,就是1 -> 2
的路徑數量。
比如:假設1
到2
有 3
33 條邊,2
到3
有 5
55 條邊,那麼根據乘法原理1 -> 2 -> 3
有 3×5
3 \times 5
3×5 條邊,在我們分別處理2
到3
的 5
55 條邊時,每一條邊都會造成 3
33 條新路徑的貢獻,這和乘法原理是相符的。對於權值的求和也可以從上面的假設去理解。
因此我們處理一條從u
指向to
,邊權為w
的邊,那麼:
s to
=∑w×
cntu
+sus_= \sum w \times cnt_u + s_u
sto=∑
w×cn
tu+
su而對於to
,路徑數量則是:
c nt
to=∑
cntu
cnt_ = \sum cnt_u
cntto
=∑cn
tu有如下**:
然而當你用這個做法興奮地提交之後,才發現自己獲得了void
dfs(
int u)
}
20
分(或者是0
分)的好成績。
你可能會抱怨道:為什麼!我樣例明明過了啊!然而作為一名 oier, 絕對不能too young too ******
,樣例往往太簡單,只是輔助理解題意的,並不能幫你找出 bug 來。
我再給一組樣例,在你讀完題解前,希望對你有所啟發:
輸入為:
輸出為:4 6 1 3 1
1 2 1
1 2 1
2 3 1
1 4 1
1 4 1
4 3 1
如圖,由於邊輸入順序的原因(我選用鏈式前向星存圖),導致4
號點在還沒有處理完,得到正確的s
與cnt
值時,就向3
傳遞了資訊,最後造成統計錯誤。
因此我們希望,改變搜尋順序,讓每乙個節點把自己的資料處理好,再向下乙個節點匯報。 有沒有這樣的方法呢?答案是有的,那就是拓撲排序。
我們記錄每乙個節點此時的入度,處理完一條邊入度自減 $ 1 $,當入度為 $ 0 $ 時加入搜尋佇列,那麼我們就可以保證每個點都得到了正確的結果。
因此最終**如下:(注意處理取模)
#include
#include
#include
using
namespace std;
const
int maxn =
1e4+
50, maxm =
5e4+
50, inf =
0x3f3f3f3f
, mod =
1e4;
int head[maxn]
, nxt[maxm]
, ver[maxm]
, edge[maxm]
, tot;
// 鏈式前向星相關
int cnt[maxn]
, s[maxn]
, in[maxn]
;// 本題相關
bool vis[maxm]
;// 記錄某條邊是否走過(或許不需要)
inline
void
add(
int u,
int v,
int w)
inline
intmul
(int a,
int b)
// 一步三取模,被取模錯誤丟分嚇怕了
inline
void
topo
(int start)
// 拓撲排序的同時進行遞推}}
intmain()
topo
(start)
;int ans =
(s[t]
+mul
(ts, cnt[t]-1
)+ mod)
% mod;
// 別忘了把路徑數量 - 1乘上乘船時間
printf
("%d"
, ans)
;return0;
}
洛谷1685 遊覽 拓撲排序 DP
順利通過了黃藥師的考驗,下面就可以盡情遊覽桃花島了!你要從桃花島的西頭開始一直玩到東頭,然後在東頭的碼頭離開。可是當你遊玩了一次後,發現桃花島的景色實在是非常的美麗!於是你還想乘船從桃花島東頭的碼頭回到西頭,再玩一遍,但是桃花島有個規矩 你可以遊覽無數遍,但是每次遊玩的路線不能完全一樣。我們把桃花島...
洛谷P4294 WC2008 遊覽計畫
教練上次課講了插頭dp,然後列出的插頭dp題目裡有這道題。本來想練練插頭dp的結果用更快更簡單的斯坦納樹解決了這道題。斯坦納樹經典題目。斯坦納樹其實並不是很難,一般用來解決在一張無向圖上選 text 個點使這 text 個點連通並且始所選邊邊權最小。那麼回到本題。設 f 表示當前在第 text 行 ...
洛谷P5049 洛谷P5022 題解 旅行
原題 資料加強版 加強版 參考你谷題解 終於調過了 又是一如既往的申必錯誤 noi plus石錘了 原題的資料允許我們 o n 2 暴力斷邊,但是加強版的資料達到了 n log n 級別,我們必須在斷邊這一環節尋求更好的解法。考慮我們進入環後在何處回溯 根據繼續走環走到的點分類 設當前已經從 b 走...