1. 程式人生 > 其它 >題解【P6122 [NEERC2016]Mole Tunnels】

題解【P6122 [NEERC2016]Mole Tunnels】

傳送門

$\texttt{Description}$

有一棵 $n$ 個節點的完全二叉樹,第 $i$ 個點最多貯存 $c_i$ 只鼴鼠,有 $m$ 只鼴鼠依次醒來,對於 $\forall k\in[1,m]$ 輸出前 $k$ 只鼴鼠醒來後最少的運動長度總和。

$1\le n\le 10^5$。

$\texttt{Solution}$

考慮暴力建圖:

  • 從 $s$ 向每隻鼴鼠睡覺的地方連一條容量為 $1$,費用為 $0$ 的邊。表示有 $1$ 只鼴鼠在某個洞裡。
  • 對於樹上一個點,連向它能到達的點,容量為 $\infty$,費用為 $1$。表示一條邊可以經過多隻鼴鼠,但是需要一個單位的長度。
  • 每個點向 $t$ 連一條容量為 $c_i$,費用為 $0$ 的邊,表示一個終點的容量。

但這樣建圖是 $\Theta(nm)$ 的,邊數也是 $nm$ 級別的,顯然 $\text{TLE}$

那麼唯一的辦法,就是用摸你肺用流的思路來優化。

考慮加入了第 $i$ 個點,$s$ 與前 $i-1$ 個點之間的流量肯定是滿流了,因為不會有無解的情況,所以每個點都到達相應的目的地。

回顧最小費用最大流的程式碼,現需要找到一條從 $s\to t$ 的增廣路。

而只有點 $i$ 滿足 $s$ 與 $i$ 的殘餘流量非 $0$,所以只需要找到 $i\to t$ 的增廣路。也就是距離 $i$ 最短,並且還有食物的點。

考慮 $\texttt{DP}$。

我們設 $f_i$ 表示第 $i$ 個點到它為根的子樹中的一個還有食物點的最近點的距離,$g_i$ 表示相應的點的編號。

子樹外的點是無法進行 $\texttt{DP}$ 的,但是我們可以暴力向上跳父親,因為這是一棵完全二叉樹,樹高是 $\log n$ 的。所以對於每一個父親 $j$ 將 $f_i$ 對 $f_j$ 進行更新。複雜度是 $\Theta(\log n)$ 的。

第一步,我們先找到距離 $i$ 最近的點,設為 $v$,並求出 $v$ 對應的 $i$ 的祖先 $u$,累計路徑距離。

之後對於 $i\to u$ 路徑上的所有邊容量減一,並暴力修改 $f$ 和 $g$ 的值。當然 $v\to u$ 路徑上也應該進行相應的修改,只不過流量加一,因為我們這裡走的是反向邊。

最後暴力從 $u$ 跳根修改即可。