1. 程式人生 > 其它 >圖論入門

圖論入門

僕の圖論本當苦手,何の事僕に適當作る?

Topo sort

定義&性質

————OI wiki

求法就是樸素選取入度為0的點,將其加入答案序列的末端。根據選取模式的不同可以得到不同的topo序
時間複雜度 \(O(n+m)\)

性質 & 應用:

  1. 基於定義性質的直接應用

    例題1:CF721C
    題意: 給出一個 \(n\) 個點 \(m\) 條邊的有向無環圖。問從 \(1\)\(n\) ,在距離不超過 \(k\) 的情況下最多經過多少點,並輸出一個方案。
    解法: 先進行拓撲排序,則拓撲序排在 \(u\) 後的點 \(v\) 均不可能到達 \(u\)。使得DP滿足了無後效性,於是直接樸素記錄路徑進行DP即可。

    例題2:CF1385E
    題意: 給你一張圖,有些邊是有向邊,有一些是無向邊,讓你給無向邊添上方向,使這張圖成為一個有向無環圖。
    解法: 根據拓撲序的性質,一個DAG上的邊,必然由拓撲序小的點指向拓撲序大的點,其實這是充要條件。於是先對有向邊進行拓撲排序,然後剩下的點拓撲序任意調整,最後按上面方法構造即可。

  2. 基於構造方法的應用

    例題1:LuoguP7054
    題意: 給定一張 \(n\)\(m\) 條邊的有向無環圖,你可以至多新增 \(k\) 條有向邊,使得這仍然是一個有向無環圖,使得字典序最小的拓撲序的字典序儘量大。輸出這個拓撲序以及方案。
    解法:
    考慮如何確定字典序最小的拓撲序?
    即普通拓撲排序過程中,用小根堆儲存入度為 \(0\)

    的點,每次取堆頂即可。
    手中有加邊的機會,意味著我們可以讓這個小根堆堆頂元素放到某些待加入的點後部,或者放我們想要的元素到小根堆中。
    更具體的,我們維護兩個集合 \(u,v\)\(u\) 表示此時入度為零的集合, \(v\) 表示我們加了邊延後放的集合,\(u\) 用小根堆維護,\(v\) 用大根堆維護。
    接下來就是分類討論:

    1. \(siz_u>1\)\(k>0\)。則往拓撲序中放入 \(u\) 堆頂元素一定不如放入 \(u\) 中其他的元素,則將 \(top_u\) 放入 \(v\) 中即可,並令 k-=1;
    2. \(siz_u=1\) 。比較 \(u\) \(v\)
      堆頂元素大小,放入較大的元素即可。
    3. \(siz_u=0\) 只能放入 \(v\) 堆頂元素了。
      此時就是最優的拓撲序,至於構造,從 \(v\) 中彈出元素時和拓撲序前一個元素連邊即可。

    例題2:LuoguP4099
    題意: 給定一張樹形圖,求拓撲序數量。
    解法:
    樹形圖,直接當成樹就可以了罷!
    我們並不關心具體的拓撲序長什麼樣子。只在乎如何能夠唯一表示。
    直接設 \(f_{i,j}\) 表示此時 \(i\) 點在已處理序列中排名第 \(j\) 的方案數,顯然此時可以做到不重不漏。
    轉移過程直接列舉 \(u,v\) 的排名,分類討論討論就出來辣!!!
    順便考察了字首和優化,動手寫寫叭。

  3. 難以分類的妙妙題
    例題1:ARC083F
    題意: 平面直角座標系上有 \(2n\) 個小球,座標為 \((x_i,y_i)\)。其中 \(y=0,x=1,2,...,n\) \(y=1,2,...,n,x=0\) 處都有一個機器人。\(y=0\) 的機器人向 \(y\) 的正方向前進,\(x=0\) 的機器人向 \(x\) 的正方向前進。每個機器人遇見第一顆小球就會同歸於盡。
    求有多少種機器人出場的排列,使得場面上小球和機器人都GG了。
    解法:
    一個常見的思路就是建立二分圖,將行列變為兩個部分的點,元素作為邊。
    一個連通塊有解,當且僅當邊數等於點數。
    形成了一個基環樹森林,然後你可以任意定向邊。問題轉化成了求拓撲序數量。
    稍作分析,則環點必定被相鄰環點支配,非環點必定被非環點支配。
    因此環上只有兩種解,列舉這兩種解。
    然後推推可得一個基環樹的答案為