[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
【输入样例一】
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 }