QOJ #8673. 最短路徑

275307894a發表於2024-08-16

題面傳送門

一年前,折戟沉沙,後面忘了。

首先我們考慮折半搜尋去做這個題。對於 \(x\),在正向的圖上跑 Dijkstra,對於 \(y\),在反圖上跑 Dijkstra。當兩邊搜到同一個點的時候,所有的最短路都可以表示成:\(x\to x'\to y'\to y\),其中 \(x'\)\(x\) 已經擴充套件過的點,\(y'\)\(y\) 已經擴充套件過的點,結合 Dijkstra 的流程不難說明這個貪心的正確性。

我們發現,在兩邊碰撞之前,每次擴充套件的點都是完全獨立的,因此如果兩邊擴充套件相同的點數,那麼相當於每次隨機抽一個點出來問什麼時候會抽出來一個點兩次,由生日悖論容易說明只需要進行 \(O(\sqrt n)\) 次擴充套件。

因為圖是隨機的,所以可以認為每個點的期望度數是 \(O(\frac{m}{n})\) 級別的,因此上述過程的複雜度就是 \(O(qmn^{-\frac{1}{2}}\log n)\) 的,可以透過 55p。

我們希望能把 \(m\) 最佳化掉。首先是 Dijkstra 部分,我們可以先對於每個點的出邊按照邊權排序,那麼對於一個點的出邊,肯定是邊權小的邊先入堆,然後才是邊權大的邊入堆,因此堆的操作次數就只與點數線性相關了。

這個時候你會發現你已經能過了,第一部分的複雜度被最佳化到了 \(O(n^{\frac{1}{2}}\log n)\),但是第二部分的複雜度還是 \(O(mn^{-\frac{1}{2}})\),雖然其實 \(O(m^{\frac{3}{4}})\) 的單次詢問看上去已經很能過了,但是我們可以做到更好。記 \(dis_{x,y}\) 表示從 \(x\) 走到 \(y\) 的最短路,中間交匯的點為 \(r\),則現在實際上已經有了一個最短路 \(dis_{x,r}+dis_{r,y}\),假設我們現在的最短路是 \(dis_{x,s}+w_{s,t}+dis_{t,y}\),則 \(w_{s,t}\leq 2\max(dis_{x,r}-dis_{x,s},dis_{r,y}-dis_{t,y})\)。如果右側沒有 \(2\) 的係數,那麼邊數就是前面 Dijkstra 遍歷的邊數,是 \(O(\sqrt n)\) 級別的,加了這個 \(2\),感性理解一下,也就乘個 \(O(1)\) 倍,因此後面部分的複雜度也就和前面一樣了。

但是更慢了怎麼會是呢?

submission

相關文章