[SDOI2017]天才黑客

題目

傳送門 to luogu

思路

動態規劃

不難想到這樣的 dp\text{dp} :用 f(x,k)f(x,k) 表示走到第 xx 個點,當前字符串狀態是 TrieTrie 樹上的 kk ,最小代價。

然後就 TT 飛了。

發現 ff 的定義有很多是無效的。因爲到達 xx 的邊只有那麼多條,在 xx 點上的時候,只可能是那些狀態。

於是更改定義,用 f(x)f(x) 表示 最後一步走的是第 xx 條邊,最小代價是多少。

此時就只有 O(m)\mathcal O(m) 的狀態數量了。

轉移就套一個 dijkstra\text{dijkstra} 即可。時間複雜度 O(mlogm)\mathcal O(m\log m) ……嗎?

注意到狀態轉移可能發生 O(m2)\mathcal O(m^2) 次。完了。真是糟糕!

優化建邊

狀態轉移的本質是邊的數量,所以我們得換一個方法。

虛樹的相關內容中,我們已經講過了,kk 個點及其 lcalca 的數量是 O(k)\mathcal O(k) 的。

TrieTrie 樹上兩個點的 lcplcp 恰好爲 depth(lca)depth(lca)

所以,對於某一個點 xx ,我們將與其相連的邊上的字符串提出來。這樣一來,就有了 deg(x)deg(x) 個字符串。

我現在想知道這 deg(x)deg(x) 個字符串,兩兩的 lcplcp 。——這不就是 deg(x)deg(x) 個點,兩兩求 lcalca 嗎?

所以我們將其按照 dfs\text{dfs} 序排序(就如我們處理虛樹那樣),不妨設其爲 v1,v2,v3,,vz(z=deg(x))v_1,v_2,v_3,\dots,v_z(z=deg(x)) ,那麼一定有(對於 1a<bz1\le a<b\le z

lcp(va,vb)=mini=ab1lcp(vi,vi+1)lcp(v_a,v_b)=\min_{i=a}^{b-1}lcp(v_i,v_{i+1})

min\min 恰好與求最短路掛鉤。我們是不是有一種獨特的構建方法呢?

對於每條入邊,將其向 dfs\text{dfs} 序比自己大的入邊連邊。這樣的邊太多,所以只連接 dfs\text{dfs} 序最小的一個。出邊同。權值統一設置爲 00

對於每個 a[1,z)a\in[1,z) ,求一對 l,rl,r ,滿足 ll 爲入邊、rr 爲出邊,並且 la<rl\le a<r 。找到 ll 最大、rr 最小的一對,將 l,rl,r 之間連邊,權值爲 lcp(va,va+1)lcp(v_a,v_{a+1})

放一張圖,形象的理解這一建邊:

在這裏插入圖片描述
本質是考慮 lcp(va,va+1)lcp(v_a,v_{a+1}) 會被哪些 lcplcp 使用到。權值爲 00 的那些邊,也就是這個用處。

一些坑點

剛纔只考慮了 dfs\text{dfs} 序較小者走到 dfs\text{dfs} 序較大者的邊,所以我們反過來再做一次即可。

但是不能在原有的基礎上直接加入這些邊,所以每個點需要分裂成四個點。

代碼

咕咕咕……

聽思路都覺得很長很難打對吧?

我試着去打了,但是我失敗了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章