1. 程式人生 > >【圖論 搜索】bzoj1064: [Noi2008]假面舞會

【圖論 搜索】bzoj1064: [Noi2008]假面舞會

des info tput 自己的 根據 比賽 u+ str src

做到最後發現還是讀題比賽

Description

一年一度的假面舞會又開始了,棟棟也興致勃勃的參加了今年的舞會。今年的面具都是主辦方特別定制的。每個參加舞會的人都可以在入場時選擇一 個自己喜歡的面具。每個面具都有一個編號,主辦方會把此編號告訴拿該面具的人。為了使舞會更有神秘感,主辦方把面具分為k (k≥3)類,並使用特殊的技術將每個面具的編號標在了面具上,只有戴第i 類面具的人才能看到戴第i+1 類面具的人的編號,戴第k 類面具的人能看到戴第1 類面具的人的編號。 參加舞會的人並不知道有多少類面具,但是棟棟對此卻特別好奇,他想自己算出有多少類面具,於是他開始在人群中收集信息。 棟棟收集的信息都是戴第幾號面具的人看到了第幾號面具的編號。如戴第2號面具的人看到了第5 號面具的編號。棟棟自己也會看到一些編號,他也會根據自己的面具編號把信息補充進去。由於並不是每個人都能記住自己所看到的全部編號,因此,棟棟收集的信 息不能保證其完整性。現在請你計算,按照棟棟目前得到的信息,至多和至少有多少類面具。由於主辦方已經聲明了k≥3,所以你必須將這條信息也考慮進去。

Input

第一行包含兩個整數n, m,用一個空格分隔,n 表示主辦方總共準備了多少個面具,m 表示棟棟收集了多少條信息。接下來m 行,每行為兩個用空格分開的整數a, b,表示戴第a 號面具的人看到了第b 號面具的編號。相同的數對a, b 在輸入文件中可能出現多次。

Output

包含兩個數,第一個數為最大可能的面具類數,第二個數為最小可能的面具類數。如果無法將所有的面具分為至少3 類,使得這些信息都滿足,則認為棟棟收集的信息有錯誤,輸出兩個-1。

Sample Input

【輸入樣例一】
6 5
1 2
2 3
3 4
4 1
3 5
【輸入樣例二】
3 3
1 2
2 1
2 3

Sample Output

【輸出樣例一】
4 4

【輸出樣例二】
-1 -1

HINT

100%的數據,滿足n ≤ 100000, m ≤ 1000000。


題目分析

naive

首先會有一個很naive的想法:

對於無環的圖找最大值:拓撲地從1開始標號dfs做下去,中途檢查邊$(u,v)$,若$v$已經被標號且$col_v≠col_u+1$,就是不合法的,隨即輸出"-1 -1"。

技術分享圖片

講上去求的是最大值所以看上去很對勁是吧?

技術分享圖片

但是遇上這麽一個環呢?7之後連的是2,所以判成無解。但是然而實際上$k=3$是成立的。

也就是說,簡單地考慮“環縮點”或者“直接染色”是行不通的。

實際做法

學了tarjan之後不要在找環只想到tarjan!

這個問題其實建個反向邊之後,可以分為兩類:

  1. 有環的
  2. 沒環的

沒環的情況:樹是很簡單的,最大值就是所有樹的最長鏈總和,最小值一定是3。

有環的情況:

DFS聽上去很基礎吧,但是切不要以為基礎的東西就沒什麽用處。

這裏依靠DFS找出每一個環的長度,並且註意到答案就是所有環長度的gcd。

可能會想到環套環的情況。不過首先DFS要永久標記訪問,復雜度是$O(n)$的,不會被卡;其次我們求的是環長度的gcd,並且如果答案合法,大環長度一定是小環的倍數,所以即便大環套在小環外,也不影響最終答案。

【圖論 搜索】bzoj1064: [Noi2008]假面舞會