解釋一下具體方案的選擇
首先我們先拋開藍書,來看看如果給了我們最終的圖,我們如何選擇,如下
於是我們所有的選擇方法就是{①③,②④,①④,②③},總之來說就是映象對稱的不能同時選擇
那麼來看藍書怎麼搞的
首先是第一種方法,其實也就是在執行普通的拓撲排序而已,但是由於佇列先進先出的性質,也就不會出現像下面的情況:我們選了①的第一個SCC,然後②的第一個SCC就不選了但是我們接下來卻選擇了②的第二個SCC而不是①的第二個SCC,導致①的第一個SCC與②的第二個SCC矛盾(這裡的第一個第二個指的是拓撲序)
然後來看看第二種方法,其實也就是利用tarjan執行完之後,SCC的逆序是一個拓撲序,但我們需要證明原圖中拓撲序的逆序列是反圖的拓撲序
其實稍微想一下就知道,我們倒著執行原圖的拓撲序,假設準備執行當前節點時,我們來想一下此時序列的意義
原圖的拓撲序中,當前節點的後面的節點是在當前節點之後刪除的,也就是說當前節點在原圖的出邊的終點一定排在原圖拓撲序列中當前節點的後面,所以在反圖上,我們倒著執行到當前節點的時候,當前節點在反圖上入邊的起點(也就是原圖上出邊的終點)一定都執行完了,所以當前節點在反圖上的度數一定是\(0\),也就沒有問題
然後還要注意到縮點之後連通塊的SCC的編號是連續的,於是像這麼寫val[i] = c[i] > c[opp[i]];
的正確性是可以保證的