[NOI2008]假面舞会(DFS)

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
 

解题思路:

原谅我过于蒟蒻。

这道题就是一个深搜。

问题就在于,如果这个图是完整的,也就是说没有残缺,那么一定整体上是一个大环。

我们称之为骨架。

我们的任务就是找出这个骨架的长度。

那么比较好办的是如果给你一条链,那么可能的答案就是3~链长的所有解。

如果给你一个环,那么答案就是所有环长约数的环。

弄清楚这个以后,我们就可以找环了。

首先,化有向变无向,出始深度为0,反边权为-1。

对于无向图建dfs树,如果存在环的话直接更新答案。

在dfs的过程中记录出现的最大和最小深度。

用三个变量来存。

链长即max-min+1

最后讨论一下是否有环即可。

代码:

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<algorithm>
  4 using std::min;
  5 using std::max;
  6 using std::sort;
  7 using std::abs;
  8 void ade(int f,int t,int v);
  9 struct ed{
 10     int f;
 11     int t;
 12     void Insert(void)
 13     {
 14         scanf("%d%d",&f,&t);
 15         return ;
 16     }
 17     void add(void)
 18     {
 19         ade(f,t,1);
 20         ade(t,f,-1);
 21         return ;
 22     }
 23     bool friend operator != (ed x,ed y)
 24     {
 25         return (x.f!=y.f)||(x.t!=y.t);
 26     }
 27 }edde[1000005];
 28 struct pnt{
 29     int hd;
 30     int dp;
 31     bool vis;
 32 }p[500000];
 33 struct ent{
 34     int twd;
 35     int lst;
 36     int vls;
 37 }e[3000000];
 38 int cnt;
 39 int n,m;
 40 int ansmin,ansmax;
 41 int cha;
 42 int Uns;
 43 void ade(int f,int t,int v)
 44 {
 45     cnt++;
 46     e[cnt].twd=t;
 47     e[cnt].lst=p[f].hd;
 48     e[cnt].vls=v;
 49     p[f].hd=cnt;
 50 }
 51 bool cmp(ed x,ed y)
 52 {
 53     if(x.f==y.f)
 54         return x.t<y.t;
 55     return x.f<y.f;
 56 }   
 57 int gcd(int x,int y)
 58 {   
 59     return (!y)?x:gcd(y,x%y);
 60 }
 61 void dfs(int x,int dep)
 62 {
 63     p[x].vis=true;
 64     p[x].dp=dep;
 65     ansmin=min(ansmin,dep);
 66     ansmax=max(ansmax,dep);
 67     for(int i=p[x].hd;i;i=e[i].lst)
 68     {
 69         int to=e[i].twd;
 70         if(p[to].vis)
 71         {
 72             Uns=gcd(abs(p[to].dp-dep-e[i].vls),Uns);
 73         }else{
 74             dfs(to,dep+e[i].vls);
 75         }
 76     }
 77     return ;
 78 }
 79 int main(void)
 80 {
 81     scanf("%d%d",&n,&m);
 82     for(int i=1;i<=m;i++)
 83         edde[i].Insert();
 84     sort(edde+1,edde+m+1,cmp);
 85     edde[1].add();
 86     for(int i=2;i<=m;i++)
 87         if(edde[i]!=edde[i-1])
 88             edde[i].add();
 89     for(int i=1;i<=n;i++)
 90     {
 91         if(!p[i].vis)
 92         {
 93             ansmax=ansmin=0;
 94             dfs(i,0);
 95             cha+=ansmax-ansmin+1;
 96         }
 97     }
 98     if(Uns>=3)
 99     {
100         for(int i=3;i<=Uns;i++)
101         {
102             if(Uns%i==0)
103             {
104                 printf("%d %d\n",Uns,i);
105                 return 0;
106             }
107         }
108         printf("%d %d",Uns,Uns);
109     }else{
110         if(Uns==0&&cha>=3)
111         {
112             printf("%d %d\n",cha,3);
113             return 0;
114         }
115         printf("-1 -1\n");
116     }
117     return 0;
118 }

 

posted @ 2018-09-11 00:28  Unstoppable728  阅读(187)  评论(0编辑  收藏  举报