【題意】
給出乙個有n個點的無向圖,其中有n-1條主要邊且這些主要邊構成一棵樹,此外還有m條其他邊,求斬斷原圖的一條主要邊和一條其他邊使得圖不連通的方案數。
注意,即使只斬斷主要邊就可以使得原圖不連通,你仍然需要繼續斬斷一條其他邊才能成為一種方案。
【解法】
考慮到原圖的乙個性質:使得原圖不連通的方案只有以下兩種情況:
1.主要邊是原圖的橋
2.主要邊和附加邊連線的兩個連通塊只有這兩條邊相連
顯然每個1產生的方案都有m種,每個2產生的方案只有一種。
考慮到原圖的主要邊構成一棵樹並且只有主要邊可能是橋,因此想到乙個性質:
如果把每條附加邊兩端點在樹上的路徑進行標記,那麼沒有被標記過的邊就是原圖的橋(注意這裡橋一定是主要邊),只被標記過一次的邊一定對應唯一的乙個2。
因此考慮使用樹鏈剖分,再加上區間修改功能,最後查詢每條邊被標記的次數,那麼沒有被標記的邊就是原圖的橋,ans+=m(因為這條邊和任意一條附加邊組合都是一種方案);只被標記了一次的邊對應唯一的乙個2,ans++;被標記超過1次的邊顯然是不能構成方案的(因為砍斷它之後它兩邊對應的兩個連通塊至少有兩條邊相連,砍斷其中的任意一條邊是無法使兩個連通塊斷開的)。
順便一提,實現區間修改單點查詢功能可以使用差分陣列,這樣單次區間修改o(1),最後逐個查詢o(n),再加上樹剖單次路徑修改o(logn)次,樹剖預處理o(n),總的複雜度為o(n+mlogn),比起線段樹單次路徑修改o(log2n),總複雜度o(nlogn+mlog2n)快了很多,並且**也更短,常數更小,也很省記憶體。
【後記】
聽出題人(magic_sheep)說本題有好幾種解法,然而本鶸渣只想到了一種,其他的還沒想出來,在此膜拜神犇。
這個解法的橋和連通塊聽上去很像圖論有關內容,實際上這個樹剖解法就是從圖論上的橋和連通塊發展來的,只不過利用了樹的性質,採用樹剖實現。因此,我覺得求橋和雙連通分量的演算法稍加組合和改造應該也是可以解決本題的。
感覺本題很有思想難度,但**實現卻非常容易(我的**僅僅80+行)。多做做這種題,很有意義。
【8.16增加】
昨天和ad神犇討論了一下,ad神犇說這個題的路徑處理部分不需要樹剖,直接用樹上差分就行。
具體做法就是把兩點那個地方的差分陣列++,把lca那裡的差分陣列-=2(因為要遮蔽lca),最後採用一遍dfs或者bfs之後按照bfs逆序處理就行。
lca可以用tarjan事先求出,這樣lca的複雜度就是o(n),單次路徑處理的複雜度也從o(logn)降到了o(1)。
學到了%%%
題目243 交換輸出
時間限制 3000 ms 記憶體限制 65535 kb 難度 1 描述 輸入n n 100 個數,找出其中最小的數,將它與最前面的數交換後輸出這些數。如果這個第乙個數就是最小的數,則保持原樣輸出,如果最小的數有相同的按照前面的交換 輸入 輸入資料有多組,每組佔一行,每行的開始是乙個整數n,表示這個測...
nyoj 243交換輸出
描述 輸入n n 100 個數,找出其中最小的數,將它與最前面的數交換後輸出這些數。如果這個第乙個數就是最小的數,則保持原樣輸出,如果最小的數有相同的按照前面的交換 輸入 輸入資料有多組,每組佔一行,每行的開始是乙個整數n,表示這個測試例項的數值的個數,跟著就是n個整數。n 0表示輸入的結束,不做處...
NYOJ 243 交換輸出
時間限制 3000 ms 記憶體限制 65535 kb 難度 1 描述 輸入n n 100 個數,找出其中最小的數,將它與最前面的數交換後輸出這些數。如果這個第乙個數就是最小的數,則保持原樣輸出,如果最小的數有相同的按照前面的交換 輸入 輸入資料有多組,每組佔一行,每行的開始是乙個整數n,表示這個測...