BZOJ 1064[NOI2008]假面舞会

1064: [Noi2008]假面舞会

Time Limit: 10 Sec  Memory Limit: 162 MB
Submit: 2044  Solved: 989
[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。

有三种情况:

1.存在链:

  那么无论答案是多少,都可以成立。

2.有如下环:

  

  两条链的差是答案的倍数。

3.有如下环:

  

  环上点数是答案的倍数。

代码如下(注意abs,可能CE):

 1 #include<iostream>
 2 #include<stdio.h>
 3 #include<string.h>
 4 #include<cmath>
 5 using namespace std;
 6 #define maxm 1000000
 7 #define maxn 100001
 8 struct node
 9 {
10     int u,v,w,nex;
11 }edge[maxm<<1|1];
12 int head[maxn],cnt=1;
13 void add(int u,int v,int w)
14 {
15     edge[++cnt]=(node){u,v,w,head[u]};
16     head[u]=cnt;
17 }
18 int n,m,nn,mm;
19 bool book[maxn],flag[maxm<<1];
20 int d[maxn],ans;
21 int gcd(int a,int b)
22 {
23     return b?gcd(b,a%b):a;
24 }
25 void dfs1(int x)
26 {
27     book[x]=true;
28     for(int i=head[x];i;i=edge[i].nex)
29     {
30         if(!book[edge[i].v])
31         {
32             d[edge[i].v]=d[x]+edge[i].w;
33             dfs1(edge[i].v);
34         }
35         else
36             ans=gcd(ans,(int)abs(0.0+d[x]+edge[i].w-d[edge[i].v]));
37     }
38 }
39 void dfs2(int x)
40 {
41     nn=min(d[x],nn);
42     mm=max(d[x],mm);
43     book[x]=true;
44     for(int i=head[x];i;i=edge[i].nex)
45         if(!flag[i])
46         {
47             flag[i]=flag[i^1]=true;
48             d[edge[i].v]=d[x]+edge[i].w;
49             dfs2(edge[i].v);
50         }
51 }
52 int main()
53 {
54     int x,y;
55     scanf("%d%d",&n,&m);
56     for(int i=1;i<=m;i++)
57     {
58         scanf("%d%d",&x,&y);
59         add(x,y,1);
60         add(y,x,-1);
61     }
62     for(int i=1;i<=n;i++)
63         if(!book[i])
64             dfs1(i);
65     if(ans)
66     {
67         if(ans<3)
68             printf("%d %d",-1,-1);
69         else
70         {
71             for(x=3;x<=ans;x++)
72                 if((ans%x)==0)
73                     break;
74             printf("%d %d",ans,x);
75         }
76         return 0;
77     }
78     memset(book,0,sizeof(book));
79     for(int i=1;i<=n;i++)
80         if(!book[i])
81         {
82             nn=mm=d[i]=0;
83             dfs2(i);
84             ans+=mm-nn+1;
85         }
86     if(ans>=3)
87         printf("%d %d",ans,3);
88     else
89         printf("%d %d",-1,-1);
90 }

时间: 2024-11-08 00:24:57

BZOJ 1064[NOI2008]假面舞会的相关文章

[bzoj 1064][NOI2008]假面舞会(dfs判断环)

题目:http://www.lydsy.com:808/JudgeOnline/problem.php?id=1064 分析: 如果a看到b,则a->b 那么: 1.如果图中有环,则说明这个环的长度肯定是答案的倍数.所以最大种类数=所有环的长度的gcd,最小种类数=所有环的长度的公约数中>=3的最小数 2.如果图中没有环且都是单独的长链,那么最大种类数=每个联通图中最长链的和,最小种类数=3(如果没有则-1) 3.要考虑一种特殊情况:a->b->c->d a->e-&g

bzoj 1064 noi2008 假面舞会题解

莫名其妙的变成了我们的noip互测题... 其实这题思想还是比较简单的,只是分类不好分而已 其实就是一个dfs的事 首先,非常明显,原题目中的所有关系可以抽象成一个图(这是...显而易见的吧...) 接下来,我们仅需在图上讨论即可 当然,这个图有几个部分组成其实并没有那么重要,毕竟,这些部分基本是互不干扰的. 所以接下来我们只需要对每一个块分别处理即可 我们来分类: 首先,如果所有块都是树,我们只需求出每个树上的最长链即可 接下来,如果存在环(包括真实的环和类环,即1-2-3-1和1-2-4+1

【BZOJ】1064: [Noi2008]假面舞会(判环+gcd+特殊的技巧)

http://www.lydsy.com/JudgeOnline/problem.php?id=1064 表示想到某一种情况就不敢写下去了.... 就是找环的gcd...好可怕.. 于是膜拜了题解.. 和我想的差不多.. 首先发现这3几种情况: 1.一条或多条单链,那么最多有sum{单链长度}个面具,最少有3个面具 2.环.主要是大环套小环QAQ,显然我们只要小环就行了QAQ环的长度为标号差,gcd能满足这个性质,因此不管它.找出所有的环即可. 3.链相交.此时最大为相交链的长度差的gcd,最小

图论 公约数 找环和链 BZOJ [NOI2008 假面舞会]

BZOJ 1064: [Noi2008]假面舞会 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 1655  Solved: 798[Submit][Status][Discuss] Description 一年一度的假面舞会又开始了,栋栋也兴致勃勃的参加了今年的舞会.今年的面具都是主办方特别定制的.每个参加舞会的人都可以在入场时选择一 个自己喜欢的面具.每个面具都有一个编号,主办方会把此编号告诉拿该面具的人.为了使舞会更有神秘感,主办方把面具分为

【BZOJ 1064】 [Noi2008]假面舞会

1064: [Noi2008]假面舞会 Time Limit: 10 Sec  Memory Limit: 162 MB Submit: 988  Solved: 507 [Submit][Status] Description 一年一度的假面舞会又开始了,栋栋也兴致勃勃的参加了今年的舞会.今年的面具都是主办方特别定制的.每个参加舞会的人都可以在入场时选择一 个自己喜欢的面具.每个面具都有一个编号,主办方会把此编号告诉拿该面具的人.为了使舞会更有神秘感,主办方把面具分为k (k≥3)类,并使用特

NOI2008假面舞会

1064: [Noi2008]假面舞会 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 883  Solved: 462[Submit][Status] Description 一年一度的假面舞会又开始了,栋栋也兴致勃勃的参加了今年的舞会.今年的面具都是主办方特别定制的.每个参加舞会的人都可以在入场时选择一 个自己喜欢的面具.每个面具都有一个编号,主办方会把此编号告诉拿该面具的人.为了使舞会更有神秘感,主办方把面具分为k (k≥3)类,并使用特殊的

[BZOJ1064][Noi2008]假面舞会

试题描述 一年一度的假面舞会又开始了,栋栋也兴致勃勃的参加了今年的舞会.今年的面具都是主办方特别定制的.每个参加舞会的人都可以在入场时选择一 个自己喜欢的面具.每个面具都有一个编号,主办方会把此编号告诉拿该面具的人.为了使舞会更有神秘感,主办方把面具分为k (k≥3)类,并使用特殊的技术将每个面具的编号标在了面具上,只有戴第i 类面具的人才能看到戴第i+1 类面具的人的编号,戴第k 类面具的人能看到戴第1 类面具的人的编号. 参加舞会的人并不知道有多少类面具,但是栋栋对此却特别好奇,他想自己算出

BZOJ1064 [Noi2008]假面舞会 【dfs】

题目 一年一度的假面舞会又开始了,栋栋也兴致勃勃的参加了今年的舞会.今年的面具都是主办方特别定制的.每个参加舞会的人都可以在入场时选择一 个自己喜欢的面具.每个面具都有一个编号,主办方会把此编号告诉拿该面具的人.为了使舞会更有神秘感,主办方把面具分为k (k≥3)类,并使用特殊的技术将每个面具的编号标在了面具上,只有戴第i 类面具的人才能看到戴第i+1 类面具的人的编号,戴第k 类面具的人能看到戴第1 类面具的人的编号. 参加舞会的人并不知道有多少类面具,但是栋栋对此却特别好奇,他想自己算出有多

【图论 搜索】bzoj1064: [Noi2008]假面舞会

做到最后发现还是读题比赛 Description 一年一度的假面舞会又开始了,栋栋也兴致勃勃的参加了今年的舞会.今年的面具都是主办方特别定制的.每个参加舞会的人都可以在入场时选择一 个自己喜欢的面具.每个面具都有一个编号,主办方会把此编号告诉拿该面具的人.为了使舞会更有神秘感,主办方把面具分为k (k≥3)类,并使用特殊的技术将每个面具的编号标在了面具上,只有戴第i 类面具的人才能看到戴第i+1 类面具的人的编号,戴第k 类面具的人能看到戴第1 类面具的人的编号. 参加舞会的人并不知道有多少类面