1. 程式人生 > >BZOJ1064[NOI2008] 假面舞會

BZOJ1064[NOI2008] 假面舞會

假面舞會

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。

題解

如果A看見了B,那麼就連AB的邊,這樣構完圖了以後,最直觀的感覺就是要找環,對於一個10元環,所有面具可以被分為2,5,10種,那麼最大的種數就是所有環長度的gcd了。

然而事情沒有那麼簡單。

可以發現有一些不合法情況:

1.png

還有一些跟他們長得很像,但是合法的情況:

3.png

上面的情況都是沒有環的,我們如何處理掉不合法情況並將合法情況納入統計範圍呢???

不妨將原圖中存在的邊權值設為1,反向邊權值設為1,這樣dfs出環的時候兩種不合法的情況環的權值為1,2,合法情況的權值都是大於等於3的,取gcd的時候自然而然就將這些情況判掉了。

如果只有鏈的話,最大答案自然就是所有鏈的長度和,最小答案為3

程式碼
#include<bits/stdc++.h>
using namespace std;
const int M=1e5+5;
struct sd{int to,val;};
vector<sd>mmp[M];
int dfn[M],ans,n,m,mind,maxd,len;
bool vis[M];
void dfs(int v,int val)
{
    if(vis[v]){ans=__gcd(ans,abs(val-dfn[v]));return;}
    vis[v]=1,dfn[v]=val,maxd=max(maxd,val),mind=min(mind,val);
    for(int i=mmp[v].size()-1;i>=0;--i)dfs(mmp[v][i].to,val+mmp[v][i].val);
}
void in(){int a,b;scanf("%d%d",&n,&m);for(int i=1;i<=m;++i)scanf("%d%d",&a,&b),mmp[a].push_back((sd){b,1}),mmp[b].push_back((sd){a,-1});}
void ac()
{
    for(int i=1;i<=n;++i)if(!vis[i])mind=maxd=0,dfs(i,0),len+=maxd-mind+1;
    if(!ans){len<3?puts("-1 -1"):printf("%d 3",len);return;}
    if(ans<3)puts("-1 -1"),exit(0);
    printf("%d",ans);for(int i=3;i<=ans;++i)if(ans%i==0)printf(" %d",i),exit(0);
}
int main(){in();ac();}