[bzoj1064][NOI2008]假面舞會
1064: [Noi2008]假面舞會
Time Limit: 10 Sec Memory Limit: 162 MB
Submit: 1580 Solved: 768
[Submit][Status][Discuss]
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。
可以把整個圖分為環和鏈來考慮。
對於鏈的情況,
對於環的情況,
現在問題就變成了怎樣求環。如果是無向圖的話,直接隨便找個點
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int N=100010;
const int M=2000010;
bool flag[N];
struct S{int st,en,va;}aa[M];
int n,m,tot,point[N],next[M],fa[N],now,minn[N],maxn[N],o[N],ans;
inline int in(){
int x=0;char ch=getchar();
while(ch<'0'||ch>'9') ch=getchar();
while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
return x;
}
inline void add(int x,int y,int z){
next[++tot]=point[x];point[x]=tot;
aa[tot].st=x;aa[tot].en=y;aa[tot].va=z;
}
inline int find(int x){
if(fa[x]!=x) fa[x]=find(fa[x]);
return fa[x];
}
inline int gcd(int x,int y){return !y?x:gcd(y,x%y);}
inline int my_abs(int x){return x<0?-x:x;}
inline void dfs(int x){
int i;
flag[x]=false;
minn[now]=min(minn[now],o[x]);
maxn[now]=max(maxn[now],o[x]);
for(i=point[x];i;i=next[i]){
if(flag[aa[i].en]){
o[aa[i].en]=o[x]+aa[i].va;
dfs(aa[i].en);
}
else ans=gcd(ans,my_abs(o[x]+aa[i].va-o[aa[i].en]));
}
}
int main(){
int i,x,y;
n=in();m=in();
for(i=1;i<=n;++i) fa[i]=i;
for(i=1;i<=m;++i){
x=in();y=in();
add(x,y,1);add(y,x,-1);
int r1=find(x),r2=find(y);
if(r1!=r2) fa[r1]=r2;
}
memset(flag,1,sizeof(flag));
memset(minn,127/3,sizeof(minn));
for(i=1;i<=n;++i)
if(flag[i]){
now=find(i);
dfs(i);
}
int ANS=0;
for(i=3;i<=ans&&!ANS;++i)
if(ans%i==0) ANS=i;
ANS=max(ANS,3);
if(!ans)
for(i=1;i<=n;++i)
if(fa[i]==i) ans+=maxn[i]-minn[i]+1;
if(ans<3) ans=ANS=-1;
printf("%d %d\n",ans,ANS);
}