洛谷 P1685 遊覽

2021-10-23 06:47:47 字數 3433 閱讀 1062

手玩樣例,我們很快(從題目後的提示)找到了 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的路徑數量。

比如:假設12有 3

33 條邊,23有 5

55 條邊,那麼根據乘法原理1 -> 2 -> 3有 3×5

3 \times 5

3×5 條邊,在我們分別處理23的 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號點在還沒有處理完,得到正確的scnt值時,就向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 走...