題目大意:好像就是先告訴你他要用26個字母的前n個字母,然后給你m條對這n個字母的限制,每一條限制這n個字母其中的兩個的先后關系,問你通過這些限制條件能不能確定這n的字母的序列。注意:當存在沖突或者拓撲排序成功時,之后的輸入不對結果造成影響。(一開始因為這個一直在wa)
思路:A<B即可以理解成存在邊A-B。n個點組成的圖,給你m條邊。問你該圖是否為DAG(無有向環圖)然后是否拓撲序唯一,最后求拓撲序。關于Kahn算法:找出所有入度為0的點,這些點都存入結果數組中(這些點拍成任意順序都可以,因為不會有其他點必須在它左邊)然后枚舉這些點(任意順序),依次判斷這個點的所有出邊(判斷之前在圖中刪除該邊),如果出邊的另一端的點,當前入度(刪除邊之后)為0,就可以把他放入結果數組之中(他已經保證了在以它為終點的所有的起點的右邊,以后再往數組里放的點,都能在它右邊),如果不是,就不入數組,但是刪的邊也不要還原(因為現在也已經保證了,該邊的起點在終點左邊)。 網上查到了對這個算法更簡單的描述:取出圖中所有入度為0的點,然后刪除這些點(包括其出邊),再一次取出所有入度為0的點。知道所有點都被取出。
對于這道題所要求的拓撲排序唯一,在Kahn算法實現過程中,不能有這么隨意,也就是說,一開始,入度為0的點只能有一個,然后每次對結果數組中的點,判斷其所有出邊的另一端是否可以進入數組的時候,有且只有一個點可以進去。然后下一次判斷出邊的點,也是唯一確定的了。如果某一次,進入的點不止一個或者沒有點入隊,那么,不能確定該拓撲序(在判斷完該圖為DAG的前提下)。 在網上查得另一種保證拓撲排序唯一的方法,對排序完成的數組中,每兩個相鄰的點進行一次判斷,判斷其之間是否有從左頂點指向右頂點的有向邊,如果沒有,那么我把這兩個點調換位置,一定可以得到另一個不同的拓撲序列。
然而還有一個問題就是:必須寫出,一條一條讀入之后,讀入了第幾條邊的時候,該拓撲序確定。 我可以加一條邊判斷一次嗎,雖然感覺很麻煩,但是它就是很麻煩啊^_^#,而且low,而且low,而且low。他并沒有給出m的大小,其實仔細想一下復雜度,如果給的這m條都是不重復的,那最多也就是26*25條,Kahn的話,復雜度我感覺應該就是26個點,每個點25條出邊,也是25*26。乘在一起,一個測試實例復雜度大概就是422500,乍一看也不高啊。另一個問題是怎么判斷該無權有向圖,不存在有向環。即為DAG圖。注意也許該圖根本不連通。
注:不能用Bellman-Ford判斷一個圖是否存在正權環回路。
整整做了一整天,還是沒做出來。把所有后臺測試數據都找出來,就是有一組不對。明天改。還是代碼實現的問題,dfs、bfs要重新練。
新聞熱點
疑難解答